@cocorof/graphier 1.3.2 → 1.4.0
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/README.md +26 -0
- package/dist/index.cjs +530 -51
- package/dist/index.cjs.map +1 -1
- package/dist/index.d.ts +98 -0
- package/dist/index.js +530 -51
- package/dist/index.js.map +1 -1
- package/package.json +2 -2
package/dist/index.js
CHANGED
|
@@ -26,7 +26,10 @@ const DEFAULT_LAYOUT = {
|
|
|
26
26
|
alphaDecay: "auto",
|
|
27
27
|
velocityDecay: 0.4,
|
|
28
28
|
settledThreshold: 5e-3,
|
|
29
|
-
spreadFactor: "auto"
|
|
29
|
+
spreadFactor: "auto",
|
|
30
|
+
dimensions: 3,
|
|
31
|
+
clusterBy: null,
|
|
32
|
+
clusterStrength: 0.05
|
|
30
33
|
};
|
|
31
34
|
function hexToRgb(hex) {
|
|
32
35
|
const c2 = hex.replace("#", "");
|
|
@@ -38,6 +41,14 @@ function rgbToHex(r, g, b) {
|
|
|
38
41
|
const hex = clamp(r) << 16 | clamp(g) << 8 | clamp(b);
|
|
39
42
|
return "#" + hex.toString(16).padStart(6, "0");
|
|
40
43
|
}
|
|
44
|
+
function luminance(hex) {
|
|
45
|
+
const [r, g, b] = hexToRgb(hex);
|
|
46
|
+
return 0.2126 * r + 0.7152 * g + 0.0722 * b;
|
|
47
|
+
}
|
|
48
|
+
function darken(hex, factor) {
|
|
49
|
+
const [r, g, b] = hexToRgb(hex);
|
|
50
|
+
return rgbToHex(r * factor, g * factor, b * factor);
|
|
51
|
+
}
|
|
41
52
|
function brighten(hex, factor) {
|
|
42
53
|
const [r, g, b] = hexToRgb(hex);
|
|
43
54
|
const t = 1 - 1 / factor;
|
|
@@ -119,10 +130,40 @@ const minimal = {
|
|
|
119
130
|
defaultLinkColor: "#444444",
|
|
120
131
|
backgroundColor: "#1a1a2e"
|
|
121
132
|
};
|
|
133
|
+
const paper = {
|
|
134
|
+
nodeColors: {},
|
|
135
|
+
// Bright (label / highlight) colors are auto-derived: on a light
|
|
136
|
+
// background resolveTheme darkens instead of whitening.
|
|
137
|
+
nodeColorsBright: {},
|
|
138
|
+
linkColors: {},
|
|
139
|
+
defaultNodeColor: "#64748b",
|
|
140
|
+
defaultLinkColor: "#b3bdcc",
|
|
141
|
+
backgroundColor: "#f6f7f9",
|
|
142
|
+
blending: "normal",
|
|
143
|
+
palette: [
|
|
144
|
+
"#2563eb",
|
|
145
|
+
// blue
|
|
146
|
+
"#d97706",
|
|
147
|
+
// amber
|
|
148
|
+
"#7c3aed",
|
|
149
|
+
// violet
|
|
150
|
+
"#db2777",
|
|
151
|
+
// pink
|
|
152
|
+
"#0891b2",
|
|
153
|
+
// cyan
|
|
154
|
+
"#16a34a",
|
|
155
|
+
// green
|
|
156
|
+
"#dc2626",
|
|
157
|
+
// red
|
|
158
|
+
"#475569"
|
|
159
|
+
// slate
|
|
160
|
+
]
|
|
161
|
+
};
|
|
122
162
|
const PRESETS = {
|
|
123
163
|
celestial,
|
|
124
164
|
neon,
|
|
125
|
-
minimal
|
|
165
|
+
minimal,
|
|
166
|
+
paper
|
|
126
167
|
};
|
|
127
168
|
const DEFAULT_THEME = {
|
|
128
169
|
nodeColors: celestial.nodeColors ?? {},
|
|
@@ -150,6 +191,8 @@ function resolveTheme(theme) {
|
|
|
150
191
|
const defaultLinkColor = config.defaultLinkColor ?? DEFAULT_THEME.defaultLinkColor;
|
|
151
192
|
const backgroundColor = config.backgroundColor ?? DEFAULT_THEME.backgroundColor;
|
|
152
193
|
const palette = config.palette ?? DEFAULT_THEME.palette;
|
|
194
|
+
const isLight = luminance(backgroundColor) > 0.5;
|
|
195
|
+
const additiveEdges = config.blending ? config.blending === "additive" : !isLight;
|
|
153
196
|
const autoAssigned = /* @__PURE__ */ new Map();
|
|
154
197
|
let nextPaletteIdx = 0;
|
|
155
198
|
function nodeColor(type) {
|
|
@@ -161,16 +204,24 @@ function resolveTheme(theme) {
|
|
|
161
204
|
}
|
|
162
205
|
return palette[autoAssigned.get(type)];
|
|
163
206
|
}
|
|
207
|
+
const emphasize = (c2) => isLight ? darken(c2, 0.72) : brighten(c2, 1.5);
|
|
164
208
|
function nodeColorBright(type) {
|
|
165
|
-
if (!type) return
|
|
209
|
+
if (!type) return emphasize(defaultNodeColor);
|
|
166
210
|
if (nodeColorsBright[type]) return nodeColorsBright[type];
|
|
167
|
-
return
|
|
211
|
+
return emphasize(nodeColor(type));
|
|
168
212
|
}
|
|
169
213
|
function linkColor(type) {
|
|
170
214
|
if (!type) return defaultLinkColor;
|
|
171
215
|
return linkColors[type] ?? defaultLinkColor;
|
|
172
216
|
}
|
|
173
|
-
return {
|
|
217
|
+
return {
|
|
218
|
+
nodeColor,
|
|
219
|
+
nodeColorBright,
|
|
220
|
+
linkColor,
|
|
221
|
+
backgroundColor,
|
|
222
|
+
isLight,
|
|
223
|
+
additiveEdges
|
|
224
|
+
};
|
|
174
225
|
}
|
|
175
226
|
function autoSpreadFactor(n) {
|
|
176
227
|
if (n <= 500) return 1;
|
|
@@ -193,6 +244,8 @@ function resolveLayoutParams(nodeCount, config) {
|
|
|
193
244
|
const postEvery = n > 5e4 ? 5 : n > 1e4 ? 3 : 2;
|
|
194
245
|
const initialRadius2 = (500 + Math.min(n, 1e4) * 0.1) * spread;
|
|
195
246
|
return {
|
|
247
|
+
dimensions: (config == null ? void 0 : config.dimensions) === 2 ? 2 : 3,
|
|
248
|
+
clusterStrength: (config == null ? void 0 : config.clusterStrength) ?? 0.05,
|
|
196
249
|
charge,
|
|
197
250
|
distanceMax,
|
|
198
251
|
theta,
|
|
@@ -204,7 +257,7 @@ function resolveLayoutParams(nodeCount, config) {
|
|
|
204
257
|
initialRadius: initialRadius2
|
|
205
258
|
};
|
|
206
259
|
}
|
|
207
|
-
const WORKER_SOURCE = '(function(){"use strict";function At(t,n,i){var e,r=1;t==null&&(t=0),n==null&&(n=0),i==null&&(i=0);function s(){var a,o=e.length,h,u=0,c=0,l=0;for(a=0;a<o;++a)h=e[a],u+=h.x||0,c+=h.y||0,l+=h.z||0;for(u=(u/o-t)*r,c=(c/o-n)*r,l=(l/o-i)*r,a=0;a<o;++a)h=e[a],u&&(h.x-=u),c&&(h.y-=c),l&&(h.z-=l)}return s.initialize=function(a){e=a},s.x=function(a){return arguments.length?(t=+a,s):t},s.y=function(a){return arguments.length?(n=+a,s):n},s.z=function(a){return arguments.length?(i=+a,s):i},s.strength=function(a){return arguments.length?(r=+a,s):r},s}function $t(t){const n=+this._x.call(null,t);return et(this.cover(n),n,t)}function et(t,n,i){if(isNaN(n))return t;var e,r=t._root,s={data:i},a=t._x0,o=t._x1,h,u,c,l,v;if(!r)return t._root=s,t;for(;r.length;)if((c=n>=(h=(a+o)/2))?a=h:o=h,e=r,!(r=r[l=+c]))return e[l]=s,t;if(u=+t._x.call(null,r.data),n===u)return s.next=r,e?e[l]=s:t._root=s,t;do e=e?e[l]=new Array(2):t._root=new Array(2),(c=n>=(h=(a+o)/2))?a=h:o=h;while((l=+c)==(v=+(u>=h)));return e[v]=r,e[l]=s,t}function mt(t){Array.isArray(t)||(t=Array.from(t));const n=t.length,i=new Float64Array(n);let e=1/0,r=-1/0;for(let s=0,a;s<n;++s)isNaN(a=+this._x.call(null,t[s]))||(i[s]=a,a<e&&(e=a),a>r&&(r=a));if(e>r)return this;this.cover(e).cover(r);for(let s=0;s<n;++s)et(this,i[s],t[s]);return this}function qt(t){if(isNaN(t=+t))return this;var n=this._x0,i=this._x1;if(isNaN(n))i=(n=Math.floor(t))+1;else{for(var e=i-n||1,r=this._root,s,a;n>t||t>=i;)switch(a=+(t<n),s=new Array(2),s[a]=r,r=s,e*=2,a){case 0:i=n+e;break;case 1:n=i-e;break}this._root&&this._root.length&&(this._root=r)}return this._x0=n,this._x1=i,this}function It(){var t=[];return this.visit(function(n){if(!n.length)do t.push(n.data);while(n=n.next)}),t}function bt(t){return arguments.length?this.cover(+t[0][0]).cover(+t[1][0]):isNaN(this._x0)?void 0:[[this._x0],[this._x1]]}function j(t,n,i){this.node=t,this.x0=n,this.x1=i}function kt(t,n){var i,e=this._x0,r,s,a=this._x1,o=[],h=this._root,u,c;for(h&&o.push(new j(h,e,a)),n==null?n=1/0:(e=t-n,a=t+n);u=o.pop();)if(!(!(h=u.node)||(r=u.x0)>a||(s=u.x1)<e))if(h.length){var l=(r+s)/2;o.push(new j(h[1],l,s),new j(h[0],r,l)),(c=+(t>=l))&&(u=o[o.length-1],o[o.length-1]=o[o.length-1-c],o[o.length-1-c]=u)}else{var v=Math.abs(t-+this._x.call(null,h.data));v<n&&(n=v,e=t-v,a=t+v,i=h.data)}return i}function Dt(t){if(isNaN(h=+this._x.call(null,t)))return this;var n,i=this._root,e,r,s,a=this._x0,o=this._x1,h,u,c,l,v;if(!i)return this;if(i.length)for(;;){if((c=h>=(u=(a+o)/2))?a=u:o=u,n=i,!(i=i[l=+c]))return this;if(!i.length)break;n[l+1&1]&&(e=n,v=l)}for(;i.data!==t;)if(r=i,!(i=i.next))return this;return(s=i.next)&&delete i.next,r?(s?r.next=s:delete r.next,this):n?(s?n[l]=s:delete n[l],(i=n[0]||n[1])&&i===(n[1]||n[0])&&!i.length&&(e?e[v]=i:this._root=i),this):(this._root=s,this)}function Et(t){for(var n=0,i=t.length;n<i;++n)this.remove(t[n]);return this}function Tt(){return this._root}function jt(){var t=0;return this.visit(function(n){if(!n.length)do++t;while(n=n.next)}),t}function Pt(t){var n=[],i,e=this._root,r,s,a;for(e&&n.push(new j(e,this._x0,this._x1));i=n.pop();)if(!t(e=i.node,s=i.x0,a=i.x1)&&e.length){var o=(s+a)/2;(r=e[1])&&n.push(new j(r,o,a)),(r=e[0])&&n.push(new j(r,s,o))}return this}function Ft(t){var n=[],i=[],e;for(this._root&&n.push(new j(this._root,this._x0,this._x1));e=n.pop();){var r=e.node;if(r.length){var s,a=e.x0,o=e.x1,h=(a+o)/2;(s=r[0])&&n.push(new j(s,a,h)),(s=r[1])&&n.push(new j(s,h,o))}i.push(e)}for(;e=i.pop();)t(e.node,e.x0,e.x1);return this}function Ot(t){return t[0]}function St(t){return arguments.length?(this._x=t,this):this._x}function rt(t,n){var i=new G(n??Ot,NaN,NaN);return t==null?i:i.addAll(t)}function G(t,n,i){this._x=t,this._x0=n,this._x1=i,this._root=void 0}function st(t){for(var n={data:t.data},i=n;t=t.next;)i=i.next={data:t.data};return n}var k=rt.prototype=G.prototype;k.copy=function(){var t=new G(this._x,this._x0,this._x1),n=this._root,i,e;if(!n)return t;if(!n.length)return t._root=st(n),t;for(i=[{source:n,target:t._root=new Array(2)}];n=i.pop();)for(var r=0;r<2;++r)(e=n.source[r])&&(e.length?i.push({source:e,target:n.target[r]=new Array(2)}):n.target[r]=st(e));return t},k.add=$t,k.addAll=mt,k.cover=qt,k.data=It,k.extent=bt,k.find=kt,k.remove=Dt,k.removeAll=Et,k.root=Tt,k.size=jt,k.visit=Pt,k.visitAfter=Ft,k.x=St;function Rt(t){const n=+this._x.call(null,t),i=+this._y.call(null,t);return at(this.cover(n,i),n,i,t)}function at(t,n,i,e){if(isNaN(n)||isNaN(i))return t;var r,s=t._root,a={data:e},o=t._x0,h=t._y0,u=t._x1,c=t._y1,l,v,y,_,N,p,f,d;if(!s)return t._root=a,t;for(;s.length;)if((N=n>=(l=(o+u)/2))?o=l:u=l,(p=i>=(v=(h+c)/2))?h=v:c=v,r=s,!(s=s[f=p<<1|N]))return r[f]=a,t;if(y=+t._x.call(null,s.data),_=+t._y.call(null,s.data),n===y&&i===_)return a.next=s,r?r[f]=a:t._root=a,t;do r=r?r[f]=new Array(4):t._root=new Array(4),(N=n>=(l=(o+u)/2))?o=l:u=l,(p=i>=(v=(h+c)/2))?h=v:c=v;while((f=p<<1|N)===(d=(_>=v)<<1|y>=l));return r[d]=s,r[f]=a,t}function Xt(t){var n,i,e=t.length,r,s,a=new Array(e),o=new Array(e),h=1/0,u=1/0,c=-1/0,l=-1/0;for(i=0;i<e;++i)isNaN(r=+this._x.call(null,n=t[i]))||isNaN(s=+this._y.call(null,n))||(a[i]=r,o[i]=s,r<h&&(h=r),r>c&&(c=r),s<u&&(u=s),s>l&&(l=s));if(h>c||u>l)return this;for(this.cover(h,u).cover(c,l),i=0;i<e;++i)at(this,a[i],o[i],t[i]);return this}function Bt(t,n){if(isNaN(t=+t)||isNaN(n=+n))return this;var i=this._x0,e=this._y0,r=this._x1,s=this._y1;if(isNaN(i))r=(i=Math.floor(t))+1,s=(e=Math.floor(n))+1;else{for(var a=r-i||1,o=this._root,h,u;i>t||t>=r||e>n||n>=s;)switch(u=(n<e)<<1|t<i,h=new Array(4),h[u]=o,o=h,a*=2,u){case 0:r=i+a,s=e+a;break;case 1:i=r-a,s=e+a;break;case 2:r=i+a,e=s-a;break;case 3:i=r-a,e=s-a;break}this._root&&this._root.length&&(this._root=o)}return this._x0=i,this._y0=e,this._x1=r,this._y1=s,this}function Ct(){var t=[];return this.visit(function(n){if(!n.length)do t.push(n.data);while(n=n.next)}),t}function Lt(t){return arguments.length?this.cover(+t[0][0],+t[0][1]).cover(+t[1][0],+t[1][1]):isNaN(this._x0)?void 0:[[this._x0,this._y0],[this._x1,this._y1]]}function I(t,n,i,e,r){this.node=t,this.x0=n,this.y0=i,this.x1=e,this.y1=r}function Yt(t,n,i){var e,r=this._x0,s=this._y0,a,o,h,u,c=this._x1,l=this._y1,v=[],y=this._root,_,N;for(y&&v.push(new I(y,r,s,c,l)),i==null?i=1/0:(r=t-i,s=n-i,c=t+i,l=n+i,i*=i);_=v.pop();)if(!(!(y=_.node)||(a=_.x0)>c||(o=_.y0)>l||(h=_.x1)<r||(u=_.y1)<s))if(y.length){var p=(a+h)/2,f=(o+u)/2;v.push(new I(y[3],p,f,h,u),new I(y[2],a,f,p,u),new I(y[1],p,o,h,f),new I(y[0],a,o,p,f)),(N=(n>=f)<<1|t>=p)&&(_=v[v.length-1],v[v.length-1]=v[v.length-1-N],v[v.length-1-N]=_)}else{var d=t-+this._x.call(null,y.data),w=n-+this._y.call(null,y.data),g=d*d+w*w;if(g<i){var x=Math.sqrt(i=g);r=t-x,s=n-x,c=t+x,l=n+x,e=y.data}}return e}function Ht(t){if(isNaN(c=+this._x.call(null,t))||isNaN(l=+this._y.call(null,t)))return this;var n,i=this._root,e,r,s,a=this._x0,o=this._y0,h=this._x1,u=this._y1,c,l,v,y,_,N,p,f;if(!i)return this;if(i.length)for(;;){if((_=c>=(v=(a+h)/2))?a=v:h=v,(N=l>=(y=(o+u)/2))?o=y:u=y,n=i,!(i=i[p=N<<1|_]))return this;if(!i.length)break;(n[p+1&3]||n[p+2&3]||n[p+3&3])&&(e=n,f=p)}for(;i.data!==t;)if(r=i,!(i=i.next))return this;return(s=i.next)&&delete i.next,r?(s?r.next=s:delete r.next,this):n?(s?n[p]=s:delete n[p],(i=n[0]||n[1]||n[2]||n[3])&&i===(n[3]||n[2]||n[1]||n[0])&&!i.length&&(e?e[f]=i:this._root=i),this):(this._root=s,this)}function Qt(t){for(var n=0,i=t.length;n<i;++n)this.remove(t[n]);return this}function Wt(){return this._root}function Zt(){var t=0;return this.visit(function(n){if(!n.length)do++t;while(n=n.next)}),t}function Gt(t){var n=[],i,e=this._root,r,s,a,o,h;for(e&&n.push(new I(e,this._x0,this._y0,this._x1,this._y1));i=n.pop();)if(!t(e=i.node,s=i.x0,a=i.y0,o=i.x1,h=i.y1)&&e.length){var u=(s+o)/2,c=(a+h)/2;(r=e[3])&&n.push(new I(r,u,c,o,h)),(r=e[2])&&n.push(new I(r,s,c,u,h)),(r=e[1])&&n.push(new I(r,u,a,o,c)),(r=e[0])&&n.push(new I(r,s,a,u,c))}return this}function Jt(t){var n=[],i=[],e;for(this._root&&n.push(new I(this._root,this._x0,this._y0,this._x1,this._y1));e=n.pop();){var r=e.node;if(r.length){var s,a=e.x0,o=e.y0,h=e.x1,u=e.y1,c=(a+h)/2,l=(o+u)/2;(s=r[0])&&n.push(new I(s,a,o,c,l)),(s=r[1])&&n.push(new I(s,c,o,h,l)),(s=r[2])&&n.push(new I(s,a,l,c,u)),(s=r[3])&&n.push(new I(s,c,l,h,u))}i.push(e)}for(;e=i.pop();)t(e.node,e.x0,e.y0,e.x1,e.y1);return this}function Kt(t){return t[0]}function Ut(t){return arguments.length?(this._x=t,this):this._x}function Vt(t){return t[1]}function tn(t){return arguments.length?(this._y=t,this):this._y}function ht(t,n,i){var e=new J(n??Kt,i??Vt,NaN,NaN,NaN,NaN);return t==null?e:e.addAll(t)}function J(t,n,i,e,r,s){this._x=t,this._y=n,this._x0=i,this._y0=e,this._x1=r,this._y1=s,this._root=void 0}function ot(t){for(var n={data:t.data},i=n;t=t.next;)i=i.next={data:t.data};return n}var b=ht.prototype=J.prototype;b.copy=function(){var t=new J(this._x,this._y,this._x0,this._y0,this._x1,this._y1),n=this._root,i,e;if(!n)return t;if(!n.length)return t._root=ot(n),t;for(i=[{source:n,target:t._root=new Array(4)}];n=i.pop();)for(var r=0;r<4;++r)(e=n.source[r])&&(e.length?i.push({source:e,target:n.target[r]=new Array(4)}):n.target[r]=ot(e));return t},b.add=Rt,b.addAll=Xt,b.cover=Bt,b.data=Ct,b.extent=Lt,b.find=Yt,b.remove=Ht,b.removeAll=Qt,b.root=Wt,b.size=Zt,b.visit=Gt,b.visitAfter=Jt,b.x=Ut,b.y=tn;function nn(t){const n=+this._x.call(null,t),i=+this._y.call(null,t),e=+this._z.call(null,t);return ft(this.cover(n,i,e),n,i,e,t)}function ft(t,n,i,e,r){if(isNaN(n)||isNaN(i)||isNaN(e))return t;var s,a=t._root,o={data:r},h=t._x0,u=t._y0,c=t._z0,l=t._x1,v=t._y1,y=t._z1,_,N,p,f,d,w,g,x,M,z,A;if(!a)return t._root=o,t;for(;a.length;)if((g=n>=(_=(h+l)/2))?h=_:l=_,(x=i>=(N=(u+v)/2))?u=N:v=N,(M=e>=(p=(c+y)/2))?c=p:y=p,s=a,!(a=a[z=M<<2|x<<1|g]))return s[z]=o,t;if(f=+t._x.call(null,a.data),d=+t._y.call(null,a.data),w=+t._z.call(null,a.data),n===f&&i===d&&e===w)return o.next=a,s?s[z]=o:t._root=o,t;do s=s?s[z]=new Array(8):t._root=new Array(8),(g=n>=(_=(h+l)/2))?h=_:l=_,(x=i>=(N=(u+v)/2))?u=N:v=N,(M=e>=(p=(c+y)/2))?c=p:y=p;while((z=M<<2|x<<1|g)===(A=(w>=p)<<2|(d>=N)<<1|f>=_));return s[A]=a,s[z]=o,t}function en(t){Array.isArray(t)||(t=Array.from(t));const n=t.length,i=new Float64Array(n),e=new Float64Array(n),r=new Float64Array(n);let s=1/0,a=1/0,o=1/0,h=-1/0,u=-1/0,c=-1/0;for(let l=0,v,y,_,N;l<n;++l)isNaN(y=+this._x.call(null,v=t[l]))||isNaN(_=+this._y.call(null,v))||isNaN(N=+this._z.call(null,v))||(i[l]=y,e[l]=_,r[l]=N,y<s&&(s=y),y>h&&(h=y),_<a&&(a=_),_>u&&(u=_),N<o&&(o=N),N>c&&(c=N));if(s>h||a>u||o>c)return this;this.cover(s,a,o).cover(h,u,c);for(let l=0;l<n;++l)ft(this,i[l],e[l],r[l],t[l]);return this}function rn(t,n,i){if(isNaN(t=+t)||isNaN(n=+n)||isNaN(i=+i))return this;var e=this._x0,r=this._y0,s=this._z0,a=this._x1,o=this._y1,h=this._z1;if(isNaN(e))a=(e=Math.floor(t))+1,o=(r=Math.floor(n))+1,h=(s=Math.floor(i))+1;else{for(var u=a-e||1,c=this._root,l,v;e>t||t>=a||r>n||n>=o||s>i||i>=h;)switch(v=(i<s)<<2|(n<r)<<1|t<e,l=new Array(8),l[v]=c,c=l,u*=2,v){case 0:a=e+u,o=r+u,h=s+u;break;case 1:e=a-u,o=r+u,h=s+u;break;case 2:a=e+u,r=o-u,h=s+u;break;case 3:e=a-u,r=o-u,h=s+u;break;case 4:a=e+u,o=r+u,s=h-u;break;case 5:e=a-u,o=r+u,s=h-u;break;case 6:a=e+u,r=o-u,s=h-u;break;case 7:e=a-u,r=o-u,s=h-u;break}this._root&&this._root.length&&(this._root=c)}return this._x0=e,this._y0=r,this._z0=s,this._x1=a,this._y1=o,this._z1=h,this}function sn(){var t=[];return this.visit(function(n){if(!n.length)do t.push(n.data);while(n=n.next)}),t}function an(t){return arguments.length?this.cover(+t[0][0],+t[0][1],+t[0][2]).cover(+t[1][0],+t[1][1],+t[1][2]):isNaN(this._x0)?void 0:[[this._x0,this._y0,this._z0],[this._x1,this._y1,this._z1]]}function $(t,n,i,e,r,s,a){this.node=t,this.x0=n,this.y0=i,this.z0=e,this.x1=r,this.y1=s,this.z1=a}function hn(t,n,i,e){var r,s=this._x0,a=this._y0,o=this._z0,h,u,c,l,v,y,_=this._x1,N=this._y1,p=this._z1,f=[],d=this._root,w,g;for(d&&f.push(new $(d,s,a,o,_,N,p)),e==null?e=1/0:(s=t-e,a=n-e,o=i-e,_=t+e,N=n+e,p=i+e,e*=e);w=f.pop();)if(!(!(d=w.node)||(h=w.x0)>_||(u=w.y0)>N||(c=w.z0)>p||(l=w.x1)<s||(v=w.y1)<a||(y=w.z1)<o))if(d.length){var x=(h+l)/2,M=(u+v)/2,z=(c+y)/2;f.push(new $(d[7],x,M,z,l,v,y),new $(d[6],h,M,z,x,v,y),new $(d[5],x,u,z,l,M,y),new $(d[4],h,u,z,x,M,y),new $(d[3],x,M,c,l,v,z),new $(d[2],h,M,c,x,v,z),new $(d[1],x,u,c,l,M,z),new $(d[0],h,u,c,x,M,z)),(g=(i>=z)<<2|(n>=M)<<1|t>=x)&&(w=f[f.length-1],f[f.length-1]=f[f.length-1-g],f[f.length-1-g]=w)}else{var A=t-+this._x.call(null,d.data),E=n-+this._y.call(null,d.data),T=i-+this._z.call(null,d.data),D=A*A+E*E+T*T;if(D<e){var m=Math.sqrt(e=D);s=t-m,a=n-m,o=i-m,_=t+m,N=n+m,p=i+m,r=d.data}}return r}const on=(t,n,i,e,r,s)=>Math.sqrt((t-e)**2+(n-r)**2+(i-s)**2);function fn(t,n,i,e){const r=[],s=t-e,a=n-e,o=i-e,h=t+e,u=n+e,c=i+e;return this.visit((l,v,y,_,N,p,f)=>{if(!l.length)do{const d=l.data;on(t,n,i,this._x(d),this._y(d),this._z(d))<=e&&r.push(d)}while(l=l.next);return v>h||y>u||_>c||N<s||p<a||f<o}),r}function un(t){if(isNaN(v=+this._x.call(null,t))||isNaN(y=+this._y.call(null,t))||isNaN(_=+this._z.call(null,t)))return this;var n,i=this._root,e,r,s,a=this._x0,o=this._y0,h=this._z0,u=this._x1,c=this._y1,l=this._z1,v,y,_,N,p,f,d,w,g,x,M;if(!i)return this;if(i.length)for(;;){if((d=v>=(N=(a+u)/2))?a=N:u=N,(w=y>=(p=(o+c)/2))?o=p:c=p,(g=_>=(f=(h+l)/2))?h=f:l=f,n=i,!(i=i[x=g<<2|w<<1|d]))return this;if(!i.length)break;(n[x+1&7]||n[x+2&7]||n[x+3&7]||n[x+4&7]||n[x+5&7]||n[x+6&7]||n[x+7&7])&&(e=n,M=x)}for(;i.data!==t;)if(r=i,!(i=i.next))return this;return(s=i.next)&&delete i.next,r?(s?r.next=s:delete r.next,this):n?(s?n[x]=s:delete n[x],(i=n[0]||n[1]||n[2]||n[3]||n[4]||n[5]||n[6]||n[7])&&i===(n[7]||n[6]||n[5]||n[4]||n[3]||n[2]||n[1]||n[0])&&!i.length&&(e?e[M]=i:this._root=i),this):(this._root=s,this)}function ln(t){for(var n=0,i=t.length;n<i;++n)this.remove(t[n]);return this}function cn(){return this._root}function _n(){var t=0;return this.visit(function(n){if(!n.length)do++t;while(n=n.next)}),t}function vn(t){var n=[],i,e=this._root,r,s,a,o,h,u,c;for(e&&n.push(new $(e,this._x0,this._y0,this._z0,this._x1,this._y1,this._z1));i=n.pop();)if(!t(e=i.node,s=i.x0,a=i.y0,o=i.z0,h=i.x1,u=i.y1,c=i.z1)&&e.length){var l=(s+h)/2,v=(a+u)/2,y=(o+c)/2;(r=e[7])&&n.push(new $(r,l,v,y,h,u,c)),(r=e[6])&&n.push(new $(r,s,v,y,l,u,c)),(r=e[5])&&n.push(new $(r,l,a,y,h,v,c)),(r=e[4])&&n.push(new $(r,s,a,y,l,v,c)),(r=e[3])&&n.push(new $(r,l,v,o,h,u,y)),(r=e[2])&&n.push(new $(r,s,v,o,l,u,y)),(r=e[1])&&n.push(new $(r,l,a,o,h,v,y)),(r=e[0])&&n.push(new $(r,s,a,o,l,v,y))}return this}function xn(t){var n=[],i=[],e;for(this._root&&n.push(new $(this._root,this._x0,this._y0,this._z0,this._x1,this._y1,this._z1));e=n.pop();){var r=e.node;if(r.length){var s,a=e.x0,o=e.y0,h=e.z0,u=e.x1,c=e.y1,l=e.z1,v=(a+u)/2,y=(o+c)/2,_=(h+l)/2;(s=r[0])&&n.push(new $(s,a,o,h,v,y,_)),(s=r[1])&&n.push(new $(s,v,o,h,u,y,_)),(s=r[2])&&n.push(new $(s,a,y,h,v,c,_)),(s=r[3])&&n.push(new $(s,v,y,h,u,c,_)),(s=r[4])&&n.push(new $(s,a,o,_,v,y,l)),(s=r[5])&&n.push(new $(s,v,o,_,u,y,l)),(s=r[6])&&n.push(new $(s,a,y,_,v,c,l)),(s=r[7])&&n.push(new $(s,v,y,_,u,c,l))}i.push(e)}for(;e=i.pop();)t(e.node,e.x0,e.y0,e.z0,e.x1,e.y1,e.z1);return this}function yn(t){return t[0]}function pn(t){return arguments.length?(this._x=t,this):this._x}function gn(t){return t[1]}function wn(t){return arguments.length?(this._y=t,this):this._y}function dn(t){return t[2]}function Nn(t){return arguments.length?(this._z=t,this):this._z}function ut(t,n,i,e){var r=new K(n??yn,i??gn,e??dn,NaN,NaN,NaN,NaN,NaN,NaN);return t==null?r:r.addAll(t)}function K(t,n,i,e,r,s,a,o,h){this._x=t,this._y=n,this._z=i,this._x0=e,this._y0=r,this._z0=s,this._x1=a,this._y1=o,this._z1=h,this._root=void 0}function lt(t){for(var n={data:t.data},i=n;t=t.next;)i=i.next={data:t.data};return n}var q=ut.prototype=K.prototype;q.copy=function(){var t=new K(this._x,this._y,this._z,this._x0,this._y0,this._z0,this._x1,this._y1,this._z1),n=this._root,i,e;if(!n)return t;if(!n.length)return t._root=lt(n),t;for(i=[{source:n,target:t._root=new Array(8)}];n=i.pop();)for(var r=0;r<8;++r)(e=n.source[r])&&(e.length?i.push({source:e,target:n.target[r]=new Array(8)}):n.target[r]=lt(e));return t},q.add=nn,q.addAll=en,q.cover=rn,q.data=sn,q.extent=an,q.find=hn,q.findAllWithinRadius=fn,q.remove=un,q.removeAll=ln,q.root=cn,q.size=_n,q.visit=vn,q.visitAfter=xn,q.x=pn,q.y=wn,q.z=Nn;function R(t){return function(){return t}}function P(t){return(t()-.5)*1e-6}function Mn(t){return t.index}function ct(t,n){var i=t.get(n);if(!i)throw new Error("node not found: "+n);return i}function zn(t){var n=Mn,i=v,e,r=R(30),s,a,o,h,u,c,l=1;t==null&&(t=[]);function v(f){return 1/Math.min(h[f.source.index],h[f.target.index])}function y(f){for(var d=0,w=t.length;d<l;++d)for(var g=0,x,M,z,A=0,E=0,T=0,D,m;g<w;++g)x=t[g],M=x.source,z=x.target,A=z.x+z.vx-M.x-M.vx||P(c),o>1&&(E=z.y+z.vy-M.y-M.vy||P(c)),o>2&&(T=z.z+z.vz-M.z-M.vz||P(c)),D=Math.sqrt(A*A+E*E+T*T),D=(D-s[g])/D*f*e[g],A*=D,E*=D,T*=D,z.vx-=A*(m=u[g]),o>1&&(z.vy-=E*m),o>2&&(z.vz-=T*m),M.vx+=A*(m=1-m),o>1&&(M.vy+=E*m),o>2&&(M.vz+=T*m)}function _(){if(a){var f,d=a.length,w=t.length,g=new Map(a.map((M,z)=>[n(M,z,a),M])),x;for(f=0,h=new Array(d);f<w;++f)x=t[f],x.index=f,typeof x.source!="object"&&(x.source=ct(g,x.source)),typeof x.target!="object"&&(x.target=ct(g,x.target)),h[x.source.index]=(h[x.source.index]||0)+1,h[x.target.index]=(h[x.target.index]||0)+1;for(f=0,u=new Array(w);f<w;++f)x=t[f],u[f]=h[x.source.index]/(h[x.source.index]+h[x.target.index]);e=new Array(w),N(),s=new Array(w),p()}}function N(){if(a)for(var f=0,d=t.length;f<d;++f)e[f]=+i(t[f],f,t)}function p(){if(a)for(var f=0,d=t.length;f<d;++f)s[f]=+r(t[f],f,t)}return y.initialize=function(f,...d){a=f,c=d.find(w=>typeof w=="function")||Math.random,o=d.find(w=>[1,2,3].includes(w))||2,_()},y.links=function(f){return arguments.length?(t=f,_(),y):t},y.id=function(f){return arguments.length?(n=f,y):n},y.iterations=function(f){return arguments.length?(l=+f,y):l},y.strength=function(f){return arguments.length?(i=typeof f=="function"?f:R(+f),N(),y):i},y.distance=function(f){return arguments.length?(r=typeof f=="function"?f:R(+f),p(),y):r},y}var An={value:()=>{}};function _t(){for(var t=0,n=arguments.length,i={},e;t<n;++t){if(!(e=arguments[t]+"")||e in i||/[\\s.]/.test(e))throw new Error("illegal type: "+e);i[e]=[]}return new H(i)}function H(t){this._=t}function $n(t,n){return t.trim().split(/^|\\s+/).map(function(i){var e="",r=i.indexOf(".");if(r>=0&&(e=i.slice(r+1),i=i.slice(0,r)),i&&!n.hasOwnProperty(i))throw new Error("unknown type: "+i);return{type:i,name:e}})}H.prototype=_t.prototype={constructor:H,on:function(t,n){var i=this._,e=$n(t+"",i),r,s=-1,a=e.length;if(arguments.length<2){for(;++s<a;)if((r=(t=e[s]).type)&&(r=mn(i[r],t.name)))return r;return}if(n!=null&&typeof n!="function")throw new Error("invalid callback: "+n);for(;++s<a;)if(r=(t=e[s]).type)i[r]=vt(i[r],t.name,n);else if(n==null)for(r in i)i[r]=vt(i[r],t.name,null);return this},copy:function(){var t={},n=this._;for(var i in n)t[i]=n[i].slice();return new H(t)},call:function(t,n){if((r=arguments.length-2)>0)for(var i=new Array(r),e=0,r,s;e<r;++e)i[e]=arguments[e+2];if(!this._.hasOwnProperty(t))throw new Error("unknown type: "+t);for(s=this._[t],e=0,r=s.length;e<r;++e)s[e].value.apply(n,i)},apply:function(t,n,i){if(!this._.hasOwnProperty(t))throw new Error("unknown type: "+t);for(var e=this._[t],r=0,s=e.length;r<s;++r)e[r].value.apply(n,i)}};function mn(t,n){for(var i=0,e=t.length,r;i<e;++i)if((r=t[i]).name===n)return r.value}function vt(t,n,i){for(var e=0,r=t.length;e<r;++e)if(t[e].name===n){t[e]=An,t=t.slice(0,e).concat(t.slice(e+1));break}return i!=null&&t.push({name:n,value:i}),t}var S=0,X=0,B=0,xt=1e3,Q,C,W=0,O=0,Z=0,L=typeof performance=="object"&&performance.now?performance:Date,yt=typeof window=="object"&&window.requestAnimationFrame?window.requestAnimationFrame.bind(window):function(t){setTimeout(t,17)};function pt(){return O||(yt(qn),O=L.now()+Z)}function qn(){O=0}function U(){this._call=this._time=this._next=null}U.prototype=gt.prototype={constructor:U,restart:function(t,n,i){if(typeof t!="function")throw new TypeError("callback is not a function");i=(i==null?pt():+i)+(n==null?0:+n),!this._next&&C!==this&&(C?C._next=this:Q=this,C=this),this._call=t,this._time=i,V()},stop:function(){this._call&&(this._call=null,this._time=1/0,V())}};function gt(t,n,i){var e=new U;return e.restart(t,n,i),e}function In(){pt(),++S;for(var t=Q,n;t;)(n=O-t._time)>=0&&t._call.call(void 0,n),t=t._next;--S}function wt(){O=(W=L.now())+Z,S=X=0;try{In()}finally{S=0,kn(),O=0}}function bn(){var t=L.now(),n=t-W;n>xt&&(Z-=n,W=t)}function kn(){for(var t,n=Q,i,e=1/0;n;)n._call?(e>n._time&&(e=n._time),t=n,n=n._next):(i=n._next,n._next=null,n=t?t._next=i:Q=i);C=t,V(e)}function V(t){if(!S){X&&(X=clearTimeout(X));var n=t-O;n>24?(t<1/0&&(X=setTimeout(wt,t-L.now()-Z)),B&&(B=clearInterval(B))):(B||(W=L.now(),B=setInterval(bn,xt)),S=1,yt(wt))}}const Dn=1664525,En=1013904223,dt=4294967296;function Tn(){let t=1;return()=>(t=(Dn*t+En)%dt)/dt}var Nt=3;function tt(t){return t.x}function Mt(t){return t.y}function jn(t){return t.z}var Pn=10,Fn=Math.PI*(3-Math.sqrt(5)),On=Math.PI*20/(9+Math.sqrt(221));function Sn(t,n){n=n||2;var i=Math.min(Nt,Math.max(1,Math.round(n))),e,r=1,s=.001,a=1-Math.pow(s,1/300),o=0,h=.6,u=new Map,c=gt(y),l=_t("tick","end"),v=Tn();t==null&&(t=[]);function y(){_(),l.call("tick",e),r<s&&(c.stop(),l.call("end",e))}function _(f){var d,w=t.length,g;f===void 0&&(f=1);for(var x=0;x<f;++x)for(r+=(o-r)*a,u.forEach(function(M){M(r)}),d=0;d<w;++d)g=t[d],g.fx==null?g.x+=g.vx*=h:(g.x=g.fx,g.vx=0),i>1&&(g.fy==null?g.y+=g.vy*=h:(g.y=g.fy,g.vy=0)),i>2&&(g.fz==null?g.z+=g.vz*=h:(g.z=g.fz,g.vz=0));return e}function N(){for(var f=0,d=t.length,w;f<d;++f){if(w=t[f],w.index=f,w.fx!=null&&(w.x=w.fx),w.fy!=null&&(w.y=w.fy),w.fz!=null&&(w.z=w.fz),isNaN(w.x)||i>1&&isNaN(w.y)||i>2&&isNaN(w.z)){var g=Pn*(i>2?Math.cbrt(.5+f):i>1?Math.sqrt(.5+f):f),x=f*Fn,M=f*On;i===1?w.x=g:i===2?(w.x=g*Math.cos(x),w.y=g*Math.sin(x)):(w.x=g*Math.sin(x)*Math.cos(M),w.y=g*Math.cos(x),w.z=g*Math.sin(x)*Math.sin(M))}(isNaN(w.vx)||i>1&&isNaN(w.vy)||i>2&&isNaN(w.vz))&&(w.vx=0,i>1&&(w.vy=0),i>2&&(w.vz=0))}}function p(f){return f.initialize&&f.initialize(t,v,i),f}return N(),e={tick:_,restart:function(){return c.restart(y),e},stop:function(){return c.stop(),e},numDimensions:function(f){return arguments.length?(i=Math.min(Nt,Math.max(1,Math.round(f))),u.forEach(p),e):i},nodes:function(f){return arguments.length?(t=f,N(),u.forEach(p),e):t},alpha:function(f){return arguments.length?(r=+f,e):r},alphaMin:function(f){return arguments.length?(s=+f,e):s},alphaDecay:function(f){return arguments.length?(a=+f,e):+a},alphaTarget:function(f){return arguments.length?(o=+f,e):o},velocityDecay:function(f){return arguments.length?(h=1-f,e):1-h},randomSource:function(f){return arguments.length?(v=f,u.forEach(p),e):v},force:function(f,d){return arguments.length>1?(d==null?u.delete(f):u.set(f,p(d)),e):u.get(f)},find:function(){var f=Array.prototype.slice.call(arguments),d=f.shift()||0,w=(i>1?f.shift():null)||0,g=(i>2?f.shift():null)||0,x=f.shift()||1/0,M=0,z=t.length,A,E,T,D,m,zt;for(x*=x,M=0;M<z;++M)m=t[M],A=d-m.x,E=w-(m.y||0),T=g-(m.z||0),D=A*A+E*E+T*T,D<x&&(zt=m,x=D);return zt},on:function(f,d){return arguments.length>1?(l.on(f,d),e):l.on(f)}}}function Rn(){var t,n,i,e,r,s=R(-30),a,o=1,h=1/0,u=.81;function c(_){var N,p=t.length,f=(n===1?rt(t,tt):n===2?ht(t,tt,Mt):n===3?ut(t,tt,Mt,jn):null).visitAfter(v);for(r=_,N=0;N<p;++N)i=t[N],f.visit(y)}function l(){if(t){var _,N=t.length,p;for(a=new Array(N),_=0;_<N;++_)p=t[_],a[p.index]=+s(p,_,t)}}function v(_){var N=0,p,f,d=0,w,g,x,M,z=_.length;if(z){for(w=g=x=M=0;M<z;++M)(p=_[M])&&(f=Math.abs(p.value))&&(N+=p.value,d+=f,w+=f*(p.x||0),g+=f*(p.y||0),x+=f*(p.z||0));N*=Math.sqrt(4/z),_.x=w/d,n>1&&(_.y=g/d),n>2&&(_.z=x/d)}else{p=_,p.x=p.data.x,n>1&&(p.y=p.data.y),n>2&&(p.z=p.data.z);do N+=a[p.data.index];while(p=p.next)}_.value=N}function y(_,N,p,f,d){if(!_.value)return!0;var w=[p,f,d][n-1],g=_.x-i.x,x=n>1?_.y-i.y:0,M=n>2?_.z-i.z:0,z=w-N,A=g*g+x*x+M*M;if(z*z/u<A)return A<h&&(g===0&&(g=P(e),A+=g*g),n>1&&x===0&&(x=P(e),A+=x*x),n>2&&M===0&&(M=P(e),A+=M*M),A<o&&(A=Math.sqrt(o*A)),i.vx+=g*_.value*r/A,n>1&&(i.vy+=x*_.value*r/A),n>2&&(i.vz+=M*_.value*r/A)),!0;if(_.length||A>=h)return;(_.data!==i||_.next)&&(g===0&&(g=P(e),A+=g*g),n>1&&x===0&&(x=P(e),A+=x*x),n>2&&M===0&&(M=P(e),A+=M*M),A<o&&(A=Math.sqrt(o*A)));do _.data!==i&&(z=a[_.data.index]*r/A,i.vx+=g*z,n>1&&(i.vy+=x*z),n>2&&(i.vz+=M*z));while(_=_.next)}return c.initialize=function(_,...N){t=_,e=N.find(p=>typeof p=="function")||Math.random,n=N.find(p=>[1,2,3].includes(p))||2,l()},c.strength=function(_){return arguments.length?(s=typeof _=="function"?_:R(+_),l(),c):s},c.distanceMin=function(_){return arguments.length?(o=_*_,c):Math.sqrt(o)},c.distanceMax=function(_){return arguments.length?(h=_*_,c):Math.sqrt(h)},c.theta=function(_){return arguments.length?(u=_*_,c):Math.sqrt(u)},c}let F=null,Y=[],nt=0,it=!1;self.onmessage=t=>{const n=t.data;if(n.type==="init"){F&&F.stop(),it=!1,nt=0;const i=n.nodes.length,e=n.params,r=n.initialPositions??{};Y=n.nodes.map((a,o)=>{const h=r[a.id];if(h)return{id:a.id,index:o,x:h.x,y:h.y,z:h.z};const u=Math.random()*Math.PI*2,c=Math.acos(2*Math.random()-1),l=e.initialRadius*(.5+Math.random()*.5);return{id:a.id,index:o,x:l*Math.sin(c)*Math.cos(u),y:l*Math.sin(c)*Math.sin(u),z:l*Math.cos(c)}});const s=n.links.map(a=>({source:a.source,target:a.target}));F=Sn(Y,3).force("charge",Rn().strength(e.charge).distanceMax(e.distanceMax).theta(e.theta)).force("link",zn(s).id(a=>a.id).distance(e.linkDistance).strength(.2)).force("center",At()).alphaDecay(e.alphaDecay).velocityDecay(e.velocityDecay),F.on("tick",()=>{nt++;const a=F.alpha();if(nt%e.postEvery!==0&&a>e.settledThreshold)return;const o=new Float32Array(i*3);for(let h=0;h<i;h++)o[h*3]=Y[h].x||0,o[h*3+1]=Y[h].y||0,o[h*3+2]=Y[h].z||0;self.postMessage({type:"positions",positions:o.buffer,alpha:a},[o.buffer]),!it&&a<e.settledThreshold&&(it=!0,self.postMessage({type:"settled"}))})}n.type==="stop"&&F&&(F.stop(),F=null)}})();\n';
|
|
260
|
+
const WORKER_SOURCE = '(function(){"use strict";function At(t,n,i){var e,r=1;t==null&&(t=0),n==null&&(n=0),i==null&&(i=0);function s(){var o,u=e.length,h,f=0,l=0,c=0;for(o=0;o<u;++o)h=e[o],f+=h.x||0,l+=h.y||0,c+=h.z||0;for(f=(f/u-t)*r,l=(l/u-n)*r,c=(c/u-i)*r,o=0;o<u;++o)h=e[o],f&&(h.x-=f),l&&(h.y-=l),c&&(h.z-=c)}return s.initialize=function(o){e=o},s.x=function(o){return arguments.length?(t=+o,s):t},s.y=function(o){return arguments.length?(n=+o,s):n},s.z=function(o){return arguments.length?(i=+o,s):i},s.strength=function(o){return arguments.length?(r=+o,s):r},s}function $t(t){const n=+this._x.call(null,t);return et(this.cover(n),n,t)}function et(t,n,i){if(isNaN(n))return t;var e,r=t._root,s={data:i},o=t._x0,u=t._x1,h,f,l,c,v;if(!r)return t._root=s,t;for(;r.length;)if((l=n>=(h=(o+u)/2))?o=h:u=h,e=r,!(r=r[c=+l]))return e[c]=s,t;if(f=+t._x.call(null,r.data),n===f)return s.next=r,e?e[c]=s:t._root=s,t;do e=e?e[c]=new Array(2):t._root=new Array(2),(l=n>=(h=(o+u)/2))?o=h:u=h;while((c=+l)==(v=+(f>=h)));return e[v]=r,e[c]=s,t}function mt(t){Array.isArray(t)||(t=Array.from(t));const n=t.length,i=new Float64Array(n);let e=1/0,r=-1/0;for(let s=0,o;s<n;++s)isNaN(o=+this._x.call(null,t[s]))||(i[s]=o,o<e&&(e=o),o>r&&(r=o));if(e>r)return this;this.cover(e).cover(r);for(let s=0;s<n;++s)et(this,i[s],t[s]);return this}function qt(t){if(isNaN(t=+t))return this;var n=this._x0,i=this._x1;if(isNaN(n))i=(n=Math.floor(t))+1;else{for(var e=i-n||1,r=this._root,s,o;n>t||t>=i;)switch(o=+(t<n),s=new Array(2),s[o]=r,r=s,e*=2,o){case 0:i=n+e;break;case 1:n=i-e;break}this._root&&this._root.length&&(this._root=r)}return this._x0=n,this._x1=i,this}function It(){var t=[];return this.visit(function(n){if(!n.length)do t.push(n.data);while(n=n.next)}),t}function bt(t){return arguments.length?this.cover(+t[0][0]).cover(+t[1][0]):isNaN(this._x0)?void 0:[[this._x0],[this._x1]]}function P(t,n,i){this.node=t,this.x0=n,this.x1=i}function kt(t,n){var i,e=this._x0,r,s,o=this._x1,u=[],h=this._root,f,l;for(h&&u.push(new P(h,e,o)),n==null?n=1/0:(e=t-n,o=t+n);f=u.pop();)if(!(!(h=f.node)||(r=f.x0)>o||(s=f.x1)<e))if(h.length){var c=(r+s)/2;u.push(new P(h[1],c,s),new P(h[0],r,c)),(l=+(t>=c))&&(f=u[u.length-1],u[u.length-1]=u[u.length-1-l],u[u.length-1-l]=f)}else{var v=Math.abs(t-+this._x.call(null,h.data));v<n&&(n=v,e=t-v,o=t+v,i=h.data)}return i}function Dt(t){if(isNaN(h=+this._x.call(null,t)))return this;var n,i=this._root,e,r,s,o=this._x0,u=this._x1,h,f,l,c,v;if(!i)return this;if(i.length)for(;;){if((l=h>=(f=(o+u)/2))?o=f:u=f,n=i,!(i=i[c=+l]))return this;if(!i.length)break;n[c+1&1]&&(e=n,v=c)}for(;i.data!==t;)if(r=i,!(i=i.next))return this;return(s=i.next)&&delete i.next,r?(s?r.next=s:delete r.next,this):n?(s?n[c]=s:delete n[c],(i=n[0]||n[1])&&i===(n[1]||n[0])&&!i.length&&(e?e[v]=i:this._root=i),this):(this._root=s,this)}function Et(t){for(var n=0,i=t.length;n<i;++n)this.remove(t[n]);return this}function Tt(){return this._root}function jt(){var t=0;return this.visit(function(n){if(!n.length)do++t;while(n=n.next)}),t}function Pt(t){var n=[],i,e=this._root,r,s,o;for(e&&n.push(new P(e,this._x0,this._x1));i=n.pop();)if(!t(e=i.node,s=i.x0,o=i.x1)&&e.length){var u=(s+o)/2;(r=e[1])&&n.push(new P(r,u,o)),(r=e[0])&&n.push(new P(r,s,u))}return this}function Ft(t){var n=[],i=[],e;for(this._root&&n.push(new P(this._root,this._x0,this._x1));e=n.pop();){var r=e.node;if(r.length){var s,o=e.x0,u=e.x1,h=(o+u)/2;(s=r[0])&&n.push(new P(s,o,h)),(s=r[1])&&n.push(new P(s,h,u))}i.push(e)}for(;e=i.pop();)t(e.node,e.x0,e.x1);return this}function St(t){return t[0]}function Ot(t){return arguments.length?(this._x=t,this):this._x}function rt(t,n){var i=new G(n??St,NaN,NaN);return t==null?i:i.addAll(t)}function G(t,n,i){this._x=t,this._x0=n,this._x1=i,this._root=void 0}function st(t){for(var n={data:t.data},i=n;t=t.next;)i=i.next={data:t.data};return n}var k=rt.prototype=G.prototype;k.copy=function(){var t=new G(this._x,this._x0,this._x1),n=this._root,i,e;if(!n)return t;if(!n.length)return t._root=st(n),t;for(i=[{source:n,target:t._root=new Array(2)}];n=i.pop();)for(var r=0;r<2;++r)(e=n.source[r])&&(e.length?i.push({source:e,target:n.target[r]=new Array(2)}):n.target[r]=st(e));return t},k.add=$t,k.addAll=mt,k.cover=qt,k.data=It,k.extent=bt,k.find=kt,k.remove=Dt,k.removeAll=Et,k.root=Tt,k.size=jt,k.visit=Pt,k.visitAfter=Ft,k.x=Ot;function Rt(t){const n=+this._x.call(null,t),i=+this._y.call(null,t);return ot(this.cover(n,i),n,i,t)}function ot(t,n,i,e){if(isNaN(n)||isNaN(i))return t;var r,s=t._root,o={data:e},u=t._x0,h=t._y0,f=t._x1,l=t._y1,c,v,y,_,g,x,a,N;if(!s)return t._root=o,t;for(;s.length;)if((g=n>=(c=(u+f)/2))?u=c:f=c,(x=i>=(v=(h+l)/2))?h=v:l=v,r=s,!(s=s[a=x<<1|g]))return r[a]=o,t;if(y=+t._x.call(null,s.data),_=+t._y.call(null,s.data),n===y&&i===_)return o.next=s,r?r[a]=o:t._root=o,t;do r=r?r[a]=new Array(4):t._root=new Array(4),(g=n>=(c=(u+f)/2))?u=c:f=c,(x=i>=(v=(h+l)/2))?h=v:l=v;while((a=x<<1|g)===(N=(_>=v)<<1|y>=c));return r[N]=s,r[a]=o,t}function Xt(t){var n,i,e=t.length,r,s,o=new Array(e),u=new Array(e),h=1/0,f=1/0,l=-1/0,c=-1/0;for(i=0;i<e;++i)isNaN(r=+this._x.call(null,n=t[i]))||isNaN(s=+this._y.call(null,n))||(o[i]=r,u[i]=s,r<h&&(h=r),r>l&&(l=r),s<f&&(f=s),s>c&&(c=s));if(h>l||f>c)return this;for(this.cover(h,f).cover(l,c),i=0;i<e;++i)ot(this,o[i],u[i],t[i]);return this}function Bt(t,n){if(isNaN(t=+t)||isNaN(n=+n))return this;var i=this._x0,e=this._y0,r=this._x1,s=this._y1;if(isNaN(i))r=(i=Math.floor(t))+1,s=(e=Math.floor(n))+1;else{for(var o=r-i||1,u=this._root,h,f;i>t||t>=r||e>n||n>=s;)switch(f=(n<e)<<1|t<i,h=new Array(4),h[f]=u,u=h,o*=2,f){case 0:r=i+o,s=e+o;break;case 1:i=r-o,s=e+o;break;case 2:r=i+o,e=s-o;break;case 3:i=r-o,e=s-o;break}this._root&&this._root.length&&(this._root=u)}return this._x0=i,this._y0=e,this._x1=r,this._y1=s,this}function Ct(){var t=[];return this.visit(function(n){if(!n.length)do t.push(n.data);while(n=n.next)}),t}function Lt(t){return arguments.length?this.cover(+t[0][0],+t[0][1]).cover(+t[1][0],+t[1][1]):isNaN(this._x0)?void 0:[[this._x0,this._y0],[this._x1,this._y1]]}function I(t,n,i,e,r){this.node=t,this.x0=n,this.y0=i,this.x1=e,this.y1=r}function Yt(t,n,i){var e,r=this._x0,s=this._y0,o,u,h,f,l=this._x1,c=this._y1,v=[],y=this._root,_,g;for(y&&v.push(new I(y,r,s,l,c)),i==null?i=1/0:(r=t-i,s=n-i,l=t+i,c=n+i,i*=i);_=v.pop();)if(!(!(y=_.node)||(o=_.x0)>l||(u=_.y0)>c||(h=_.x1)<r||(f=_.y1)<s))if(y.length){var x=(o+h)/2,a=(u+f)/2;v.push(new I(y[3],x,a,h,f),new I(y[2],o,a,x,f),new I(y[1],x,u,h,a),new I(y[0],o,u,x,a)),(g=(n>=a)<<1|t>=x)&&(_=v[v.length-1],v[v.length-1]=v[v.length-1-g],v[v.length-1-g]=_)}else{var N=t-+this._x.call(null,y.data),d=n-+this._y.call(null,y.data),w=N*N+d*d;if(w<i){var p=Math.sqrt(i=w);r=t-p,s=n-p,l=t+p,c=n+p,e=y.data}}return e}function Ht(t){if(isNaN(l=+this._x.call(null,t))||isNaN(c=+this._y.call(null,t)))return this;var n,i=this._root,e,r,s,o=this._x0,u=this._y0,h=this._x1,f=this._y1,l,c,v,y,_,g,x,a;if(!i)return this;if(i.length)for(;;){if((_=l>=(v=(o+h)/2))?o=v:h=v,(g=c>=(y=(u+f)/2))?u=y:f=y,n=i,!(i=i[x=g<<1|_]))return this;if(!i.length)break;(n[x+1&3]||n[x+2&3]||n[x+3&3])&&(e=n,a=x)}for(;i.data!==t;)if(r=i,!(i=i.next))return this;return(s=i.next)&&delete i.next,r?(s?r.next=s:delete r.next,this):n?(s?n[x]=s:delete n[x],(i=n[0]||n[1]||n[2]||n[3])&&i===(n[3]||n[2]||n[1]||n[0])&&!i.length&&(e?e[a]=i:this._root=i),this):(this._root=s,this)}function Qt(t){for(var n=0,i=t.length;n<i;++n)this.remove(t[n]);return this}function Wt(){return this._root}function Zt(){var t=0;return this.visit(function(n){if(!n.length)do++t;while(n=n.next)}),t}function Gt(t){var n=[],i,e=this._root,r,s,o,u,h;for(e&&n.push(new I(e,this._x0,this._y0,this._x1,this._y1));i=n.pop();)if(!t(e=i.node,s=i.x0,o=i.y0,u=i.x1,h=i.y1)&&e.length){var f=(s+u)/2,l=(o+h)/2;(r=e[3])&&n.push(new I(r,f,l,u,h)),(r=e[2])&&n.push(new I(r,s,l,f,h)),(r=e[1])&&n.push(new I(r,f,o,u,l)),(r=e[0])&&n.push(new I(r,s,o,f,l))}return this}function Jt(t){var n=[],i=[],e;for(this._root&&n.push(new I(this._root,this._x0,this._y0,this._x1,this._y1));e=n.pop();){var r=e.node;if(r.length){var s,o=e.x0,u=e.y0,h=e.x1,f=e.y1,l=(o+h)/2,c=(u+f)/2;(s=r[0])&&n.push(new I(s,o,u,l,c)),(s=r[1])&&n.push(new I(s,l,u,h,c)),(s=r[2])&&n.push(new I(s,o,c,l,f)),(s=r[3])&&n.push(new I(s,l,c,h,f))}i.push(e)}for(;e=i.pop();)t(e.node,e.x0,e.y0,e.x1,e.y1);return this}function Kt(t){return t[0]}function Ut(t){return arguments.length?(this._x=t,this):this._x}function Vt(t){return t[1]}function tn(t){return arguments.length?(this._y=t,this):this._y}function ht(t,n,i){var e=new J(n??Kt,i??Vt,NaN,NaN,NaN,NaN);return t==null?e:e.addAll(t)}function J(t,n,i,e,r,s){this._x=t,this._y=n,this._x0=i,this._y0=e,this._x1=r,this._y1=s,this._root=void 0}function at(t){for(var n={data:t.data},i=n;t=t.next;)i=i.next={data:t.data};return n}var b=ht.prototype=J.prototype;b.copy=function(){var t=new J(this._x,this._y,this._x0,this._y0,this._x1,this._y1),n=this._root,i,e;if(!n)return t;if(!n.length)return t._root=at(n),t;for(i=[{source:n,target:t._root=new Array(4)}];n=i.pop();)for(var r=0;r<4;++r)(e=n.source[r])&&(e.length?i.push({source:e,target:n.target[r]=new Array(4)}):n.target[r]=at(e));return t},b.add=Rt,b.addAll=Xt,b.cover=Bt,b.data=Ct,b.extent=Lt,b.find=Yt,b.remove=Ht,b.removeAll=Qt,b.root=Wt,b.size=Zt,b.visit=Gt,b.visitAfter=Jt,b.x=Ut,b.y=tn;function nn(t){const n=+this._x.call(null,t),i=+this._y.call(null,t),e=+this._z.call(null,t);return ft(this.cover(n,i,e),n,i,e,t)}function ft(t,n,i,e,r){if(isNaN(n)||isNaN(i)||isNaN(e))return t;var s,o=t._root,u={data:r},h=t._x0,f=t._y0,l=t._z0,c=t._x1,v=t._y1,y=t._z1,_,g,x,a,N,d,w,p,M,z,A;if(!o)return t._root=u,t;for(;o.length;)if((w=n>=(_=(h+c)/2))?h=_:c=_,(p=i>=(g=(f+v)/2))?f=g:v=g,(M=e>=(x=(l+y)/2))?l=x:y=x,s=o,!(o=o[z=M<<2|p<<1|w]))return s[z]=u,t;if(a=+t._x.call(null,o.data),N=+t._y.call(null,o.data),d=+t._z.call(null,o.data),n===a&&i===N&&e===d)return u.next=o,s?s[z]=u:t._root=u,t;do s=s?s[z]=new Array(8):t._root=new Array(8),(w=n>=(_=(h+c)/2))?h=_:c=_,(p=i>=(g=(f+v)/2))?f=g:v=g,(M=e>=(x=(l+y)/2))?l=x:y=x;while((z=M<<2|p<<1|w)===(A=(d>=x)<<2|(N>=g)<<1|a>=_));return s[A]=o,s[z]=u,t}function en(t){Array.isArray(t)||(t=Array.from(t));const n=t.length,i=new Float64Array(n),e=new Float64Array(n),r=new Float64Array(n);let s=1/0,o=1/0,u=1/0,h=-1/0,f=-1/0,l=-1/0;for(let c=0,v,y,_,g;c<n;++c)isNaN(y=+this._x.call(null,v=t[c]))||isNaN(_=+this._y.call(null,v))||isNaN(g=+this._z.call(null,v))||(i[c]=y,e[c]=_,r[c]=g,y<s&&(s=y),y>h&&(h=y),_<o&&(o=_),_>f&&(f=_),g<u&&(u=g),g>l&&(l=g));if(s>h||o>f||u>l)return this;this.cover(s,o,u).cover(h,f,l);for(let c=0;c<n;++c)ft(this,i[c],e[c],r[c],t[c]);return this}function rn(t,n,i){if(isNaN(t=+t)||isNaN(n=+n)||isNaN(i=+i))return this;var e=this._x0,r=this._y0,s=this._z0,o=this._x1,u=this._y1,h=this._z1;if(isNaN(e))o=(e=Math.floor(t))+1,u=(r=Math.floor(n))+1,h=(s=Math.floor(i))+1;else{for(var f=o-e||1,l=this._root,c,v;e>t||t>=o||r>n||n>=u||s>i||i>=h;)switch(v=(i<s)<<2|(n<r)<<1|t<e,c=new Array(8),c[v]=l,l=c,f*=2,v){case 0:o=e+f,u=r+f,h=s+f;break;case 1:e=o-f,u=r+f,h=s+f;break;case 2:o=e+f,r=u-f,h=s+f;break;case 3:e=o-f,r=u-f,h=s+f;break;case 4:o=e+f,u=r+f,s=h-f;break;case 5:e=o-f,u=r+f,s=h-f;break;case 6:o=e+f,r=u-f,s=h-f;break;case 7:e=o-f,r=u-f,s=h-f;break}this._root&&this._root.length&&(this._root=l)}return this._x0=e,this._y0=r,this._z0=s,this._x1=o,this._y1=u,this._z1=h,this}function sn(){var t=[];return this.visit(function(n){if(!n.length)do t.push(n.data);while(n=n.next)}),t}function on(t){return arguments.length?this.cover(+t[0][0],+t[0][1],+t[0][2]).cover(+t[1][0],+t[1][1],+t[1][2]):isNaN(this._x0)?void 0:[[this._x0,this._y0,this._z0],[this._x1,this._y1,this._z1]]}function $(t,n,i,e,r,s,o){this.node=t,this.x0=n,this.y0=i,this.z0=e,this.x1=r,this.y1=s,this.z1=o}function hn(t,n,i,e){var r,s=this._x0,o=this._y0,u=this._z0,h,f,l,c,v,y,_=this._x1,g=this._y1,x=this._z1,a=[],N=this._root,d,w;for(N&&a.push(new $(N,s,o,u,_,g,x)),e==null?e=1/0:(s=t-e,o=n-e,u=i-e,_=t+e,g=n+e,x=i+e,e*=e);d=a.pop();)if(!(!(N=d.node)||(h=d.x0)>_||(f=d.y0)>g||(l=d.z0)>x||(c=d.x1)<s||(v=d.y1)<o||(y=d.z1)<u))if(N.length){var p=(h+c)/2,M=(f+v)/2,z=(l+y)/2;a.push(new $(N[7],p,M,z,c,v,y),new $(N[6],h,M,z,p,v,y),new $(N[5],p,f,z,c,M,y),new $(N[4],h,f,z,p,M,y),new $(N[3],p,M,l,c,v,z),new $(N[2],h,M,l,p,v,z),new $(N[1],p,f,l,c,M,z),new $(N[0],h,f,l,p,M,z)),(w=(i>=z)<<2|(n>=M)<<1|t>=p)&&(d=a[a.length-1],a[a.length-1]=a[a.length-1-w],a[a.length-1-w]=d)}else{var A=t-+this._x.call(null,N.data),E=n-+this._y.call(null,N.data),T=i-+this._z.call(null,N.data),D=A*A+E*E+T*T;if(D<e){var m=Math.sqrt(e=D);s=t-m,o=n-m,u=i-m,_=t+m,g=n+m,x=i+m,r=N.data}}return r}const an=(t,n,i,e,r,s)=>Math.sqrt((t-e)**2+(n-r)**2+(i-s)**2);function fn(t,n,i,e){const r=[],s=t-e,o=n-e,u=i-e,h=t+e,f=n+e,l=i+e;return this.visit((c,v,y,_,g,x,a)=>{if(!c.length)do{const N=c.data;an(t,n,i,this._x(N),this._y(N),this._z(N))<=e&&r.push(N)}while(c=c.next);return v>h||y>f||_>l||g<s||x<o||a<u}),r}function un(t){if(isNaN(v=+this._x.call(null,t))||isNaN(y=+this._y.call(null,t))||isNaN(_=+this._z.call(null,t)))return this;var n,i=this._root,e,r,s,o=this._x0,u=this._y0,h=this._z0,f=this._x1,l=this._y1,c=this._z1,v,y,_,g,x,a,N,d,w,p,M;if(!i)return this;if(i.length)for(;;){if((N=v>=(g=(o+f)/2))?o=g:f=g,(d=y>=(x=(u+l)/2))?u=x:l=x,(w=_>=(a=(h+c)/2))?h=a:c=a,n=i,!(i=i[p=w<<2|d<<1|N]))return this;if(!i.length)break;(n[p+1&7]||n[p+2&7]||n[p+3&7]||n[p+4&7]||n[p+5&7]||n[p+6&7]||n[p+7&7])&&(e=n,M=p)}for(;i.data!==t;)if(r=i,!(i=i.next))return this;return(s=i.next)&&delete i.next,r?(s?r.next=s:delete r.next,this):n?(s?n[p]=s:delete n[p],(i=n[0]||n[1]||n[2]||n[3]||n[4]||n[5]||n[6]||n[7])&&i===(n[7]||n[6]||n[5]||n[4]||n[3]||n[2]||n[1]||n[0])&&!i.length&&(e?e[M]=i:this._root=i),this):(this._root=s,this)}function ln(t){for(var n=0,i=t.length;n<i;++n)this.remove(t[n]);return this}function cn(){return this._root}function _n(){var t=0;return this.visit(function(n){if(!n.length)do++t;while(n=n.next)}),t}function vn(t){var n=[],i,e=this._root,r,s,o,u,h,f,l;for(e&&n.push(new $(e,this._x0,this._y0,this._z0,this._x1,this._y1,this._z1));i=n.pop();)if(!t(e=i.node,s=i.x0,o=i.y0,u=i.z0,h=i.x1,f=i.y1,l=i.z1)&&e.length){var c=(s+h)/2,v=(o+f)/2,y=(u+l)/2;(r=e[7])&&n.push(new $(r,c,v,y,h,f,l)),(r=e[6])&&n.push(new $(r,s,v,y,c,f,l)),(r=e[5])&&n.push(new $(r,c,o,y,h,v,l)),(r=e[4])&&n.push(new $(r,s,o,y,c,v,l)),(r=e[3])&&n.push(new $(r,c,v,u,h,f,y)),(r=e[2])&&n.push(new $(r,s,v,u,c,f,y)),(r=e[1])&&n.push(new $(r,c,o,u,h,v,y)),(r=e[0])&&n.push(new $(r,s,o,u,c,v,y))}return this}function xn(t){var n=[],i=[],e;for(this._root&&n.push(new $(this._root,this._x0,this._y0,this._z0,this._x1,this._y1,this._z1));e=n.pop();){var r=e.node;if(r.length){var s,o=e.x0,u=e.y0,h=e.z0,f=e.x1,l=e.y1,c=e.z1,v=(o+f)/2,y=(u+l)/2,_=(h+c)/2;(s=r[0])&&n.push(new $(s,o,u,h,v,y,_)),(s=r[1])&&n.push(new $(s,v,u,h,f,y,_)),(s=r[2])&&n.push(new $(s,o,y,h,v,l,_)),(s=r[3])&&n.push(new $(s,v,y,h,f,l,_)),(s=r[4])&&n.push(new $(s,o,u,_,v,y,c)),(s=r[5])&&n.push(new $(s,v,u,_,f,y,c)),(s=r[6])&&n.push(new $(s,o,y,_,v,l,c)),(s=r[7])&&n.push(new $(s,v,y,_,f,l,c))}i.push(e)}for(;e=i.pop();)t(e.node,e.x0,e.y0,e.z0,e.x1,e.y1,e.z1);return this}function yn(t){return t[0]}function pn(t){return arguments.length?(this._x=t,this):this._x}function gn(t){return t[1]}function wn(t){return arguments.length?(this._y=t,this):this._y}function dn(t){return t[2]}function Nn(t){return arguments.length?(this._z=t,this):this._z}function ut(t,n,i,e){var r=new K(n??yn,i??gn,e??dn,NaN,NaN,NaN,NaN,NaN,NaN);return t==null?r:r.addAll(t)}function K(t,n,i,e,r,s,o,u,h){this._x=t,this._y=n,this._z=i,this._x0=e,this._y0=r,this._z0=s,this._x1=o,this._y1=u,this._z1=h,this._root=void 0}function lt(t){for(var n={data:t.data},i=n;t=t.next;)i=i.next={data:t.data};return n}var q=ut.prototype=K.prototype;q.copy=function(){var t=new K(this._x,this._y,this._z,this._x0,this._y0,this._z0,this._x1,this._y1,this._z1),n=this._root,i,e;if(!n)return t;if(!n.length)return t._root=lt(n),t;for(i=[{source:n,target:t._root=new Array(8)}];n=i.pop();)for(var r=0;r<8;++r)(e=n.source[r])&&(e.length?i.push({source:e,target:n.target[r]=new Array(8)}):n.target[r]=lt(e));return t},q.add=nn,q.addAll=en,q.cover=rn,q.data=sn,q.extent=on,q.find=hn,q.findAllWithinRadius=fn,q.remove=un,q.removeAll=ln,q.root=cn,q.size=_n,q.visit=vn,q.visitAfter=xn,q.x=pn,q.y=wn,q.z=Nn;function X(t){return function(){return t}}function F(t){return(t()-.5)*1e-6}function Mn(t){return t.index}function ct(t,n){var i=t.get(n);if(!i)throw new Error("node not found: "+n);return i}function zn(t){var n=Mn,i=v,e,r=X(30),s,o,u,h,f,l,c=1;t==null&&(t=[]);function v(a){return 1/Math.min(h[a.source.index],h[a.target.index])}function y(a){for(var N=0,d=t.length;N<c;++N)for(var w=0,p,M,z,A=0,E=0,T=0,D,m;w<d;++w)p=t[w],M=p.source,z=p.target,A=z.x+z.vx-M.x-M.vx||F(l),u>1&&(E=z.y+z.vy-M.y-M.vy||F(l)),u>2&&(T=z.z+z.vz-M.z-M.vz||F(l)),D=Math.sqrt(A*A+E*E+T*T),D=(D-s[w])/D*a*e[w],A*=D,E*=D,T*=D,z.vx-=A*(m=f[w]),u>1&&(z.vy-=E*m),u>2&&(z.vz-=T*m),M.vx+=A*(m=1-m),u>1&&(M.vy+=E*m),u>2&&(M.vz+=T*m)}function _(){if(o){var a,N=o.length,d=t.length,w=new Map(o.map((M,z)=>[n(M,z,o),M])),p;for(a=0,h=new Array(N);a<d;++a)p=t[a],p.index=a,typeof p.source!="object"&&(p.source=ct(w,p.source)),typeof p.target!="object"&&(p.target=ct(w,p.target)),h[p.source.index]=(h[p.source.index]||0)+1,h[p.target.index]=(h[p.target.index]||0)+1;for(a=0,f=new Array(d);a<d;++a)p=t[a],f[a]=h[p.source.index]/(h[p.source.index]+h[p.target.index]);e=new Array(d),g(),s=new Array(d),x()}}function g(){if(o)for(var a=0,N=t.length;a<N;++a)e[a]=+i(t[a],a,t)}function x(){if(o)for(var a=0,N=t.length;a<N;++a)s[a]=+r(t[a],a,t)}return y.initialize=function(a,...N){o=a,l=N.find(d=>typeof d=="function")||Math.random,u=N.find(d=>[1,2,3].includes(d))||2,_()},y.links=function(a){return arguments.length?(t=a,_(),y):t},y.id=function(a){return arguments.length?(n=a,y):n},y.iterations=function(a){return arguments.length?(c=+a,y):c},y.strength=function(a){return arguments.length?(i=typeof a=="function"?a:X(+a),g(),y):i},y.distance=function(a){return arguments.length?(r=typeof a=="function"?a:X(+a),x(),y):r},y}var An={value:()=>{}};function _t(){for(var t=0,n=arguments.length,i={},e;t<n;++t){if(!(e=arguments[t]+"")||e in i||/[\\s.]/.test(e))throw new Error("illegal type: "+e);i[e]=[]}return new H(i)}function H(t){this._=t}function $n(t,n){return t.trim().split(/^|\\s+/).map(function(i){var e="",r=i.indexOf(".");if(r>=0&&(e=i.slice(r+1),i=i.slice(0,r)),i&&!n.hasOwnProperty(i))throw new Error("unknown type: "+i);return{type:i,name:e}})}H.prototype=_t.prototype={constructor:H,on:function(t,n){var i=this._,e=$n(t+"",i),r,s=-1,o=e.length;if(arguments.length<2){for(;++s<o;)if((r=(t=e[s]).type)&&(r=mn(i[r],t.name)))return r;return}if(n!=null&&typeof n!="function")throw new Error("invalid callback: "+n);for(;++s<o;)if(r=(t=e[s]).type)i[r]=vt(i[r],t.name,n);else if(n==null)for(r in i)i[r]=vt(i[r],t.name,null);return this},copy:function(){var t={},n=this._;for(var i in n)t[i]=n[i].slice();return new H(t)},call:function(t,n){if((r=arguments.length-2)>0)for(var i=new Array(r),e=0,r,s;e<r;++e)i[e]=arguments[e+2];if(!this._.hasOwnProperty(t))throw new Error("unknown type: "+t);for(s=this._[t],e=0,r=s.length;e<r;++e)s[e].value.apply(n,i)},apply:function(t,n,i){if(!this._.hasOwnProperty(t))throw new Error("unknown type: "+t);for(var e=this._[t],r=0,s=e.length;r<s;++r)e[r].value.apply(n,i)}};function mn(t,n){for(var i=0,e=t.length,r;i<e;++i)if((r=t[i]).name===n)return r.value}function vt(t,n,i){for(var e=0,r=t.length;e<r;++e)if(t[e].name===n){t[e]=An,t=t.slice(0,e).concat(t.slice(e+1));break}return i!=null&&t.push({name:n,value:i}),t}var R=0,B=0,C=0,xt=1e3,Q,L,W=0,O=0,Z=0,Y=typeof performance=="object"&&performance.now?performance:Date,yt=typeof window=="object"&&window.requestAnimationFrame?window.requestAnimationFrame.bind(window):function(t){setTimeout(t,17)};function pt(){return O||(yt(qn),O=Y.now()+Z)}function qn(){O=0}function U(){this._call=this._time=this._next=null}U.prototype=gt.prototype={constructor:U,restart:function(t,n,i){if(typeof t!="function")throw new TypeError("callback is not a function");i=(i==null?pt():+i)+(n==null?0:+n),!this._next&&L!==this&&(L?L._next=this:Q=this,L=this),this._call=t,this._time=i,V()},stop:function(){this._call&&(this._call=null,this._time=1/0,V())}};function gt(t,n,i){var e=new U;return e.restart(t,n,i),e}function In(){pt(),++R;for(var t=Q,n;t;)(n=O-t._time)>=0&&t._call.call(void 0,n),t=t._next;--R}function wt(){O=(W=Y.now())+Z,R=B=0;try{In()}finally{R=0,kn(),O=0}}function bn(){var t=Y.now(),n=t-W;n>xt&&(Z-=n,W=t)}function kn(){for(var t,n=Q,i,e=1/0;n;)n._call?(e>n._time&&(e=n._time),t=n,n=n._next):(i=n._next,n._next=null,n=t?t._next=i:Q=i);L=t,V(e)}function V(t){if(!R){B&&(B=clearTimeout(B));var n=t-O;n>24?(t<1/0&&(B=setTimeout(wt,t-Y.now()-Z)),C&&(C=clearInterval(C))):(C||(W=Y.now(),C=setInterval(bn,xt)),R=1,yt(wt))}}const Dn=1664525,En=1013904223,dt=4294967296;function Tn(){let t=1;return()=>(t=(Dn*t+En)%dt)/dt}var Nt=3;function tt(t){return t.x}function Mt(t){return t.y}function jn(t){return t.z}var Pn=10,Fn=Math.PI*(3-Math.sqrt(5)),Sn=Math.PI*20/(9+Math.sqrt(221));function On(t,n){n=n||2;var i=Math.min(Nt,Math.max(1,Math.round(n))),e,r=1,s=.001,o=1-Math.pow(s,1/300),u=0,h=.6,f=new Map,l=gt(y),c=_t("tick","end"),v=Tn();t==null&&(t=[]);function y(){_(),c.call("tick",e),r<s&&(l.stop(),c.call("end",e))}function _(a){var N,d=t.length,w;a===void 0&&(a=1);for(var p=0;p<a;++p)for(r+=(u-r)*o,f.forEach(function(M){M(r)}),N=0;N<d;++N)w=t[N],w.fx==null?w.x+=w.vx*=h:(w.x=w.fx,w.vx=0),i>1&&(w.fy==null?w.y+=w.vy*=h:(w.y=w.fy,w.vy=0)),i>2&&(w.fz==null?w.z+=w.vz*=h:(w.z=w.fz,w.vz=0));return e}function g(){for(var a=0,N=t.length,d;a<N;++a){if(d=t[a],d.index=a,d.fx!=null&&(d.x=d.fx),d.fy!=null&&(d.y=d.fy),d.fz!=null&&(d.z=d.fz),isNaN(d.x)||i>1&&isNaN(d.y)||i>2&&isNaN(d.z)){var w=Pn*(i>2?Math.cbrt(.5+a):i>1?Math.sqrt(.5+a):a),p=a*Fn,M=a*Sn;i===1?d.x=w:i===2?(d.x=w*Math.cos(p),d.y=w*Math.sin(p)):(d.x=w*Math.sin(p)*Math.cos(M),d.y=w*Math.cos(p),d.z=w*Math.sin(p)*Math.sin(M))}(isNaN(d.vx)||i>1&&isNaN(d.vy)||i>2&&isNaN(d.vz))&&(d.vx=0,i>1&&(d.vy=0),i>2&&(d.vz=0))}}function x(a){return a.initialize&&a.initialize(t,v,i),a}return g(),e={tick:_,restart:function(){return l.restart(y),e},stop:function(){return l.stop(),e},numDimensions:function(a){return arguments.length?(i=Math.min(Nt,Math.max(1,Math.round(a))),f.forEach(x),e):i},nodes:function(a){return arguments.length?(t=a,g(),f.forEach(x),e):t},alpha:function(a){return arguments.length?(r=+a,e):r},alphaMin:function(a){return arguments.length?(s=+a,e):s},alphaDecay:function(a){return arguments.length?(o=+a,e):+o},alphaTarget:function(a){return arguments.length?(u=+a,e):u},velocityDecay:function(a){return arguments.length?(h=1-a,e):1-h},randomSource:function(a){return arguments.length?(v=a,f.forEach(x),e):v},force:function(a,N){return arguments.length>1?(N==null?f.delete(a):f.set(a,x(N)),e):f.get(a)},find:function(){var a=Array.prototype.slice.call(arguments),N=a.shift()||0,d=(i>1?a.shift():null)||0,w=(i>2?a.shift():null)||0,p=a.shift()||1/0,M=0,z=t.length,A,E,T,D,m,zt;for(p*=p,M=0;M<z;++M)m=t[M],A=N-m.x,E=d-(m.y||0),T=w-(m.z||0),D=A*A+E*E+T*T,D<p&&(zt=m,p=D);return zt},on:function(a,N){return arguments.length>1?(c.on(a,N),e):c.on(a)}}}function Rn(){var t,n,i,e,r,s=X(-30),o,u=1,h=1/0,f=.81;function l(_){var g,x=t.length,a=(n===1?rt(t,tt):n===2?ht(t,tt,Mt):n===3?ut(t,tt,Mt,jn):null).visitAfter(v);for(r=_,g=0;g<x;++g)i=t[g],a.visit(y)}function c(){if(t){var _,g=t.length,x;for(o=new Array(g),_=0;_<g;++_)x=t[_],o[x.index]=+s(x,_,t)}}function v(_){var g=0,x,a,N=0,d,w,p,M,z=_.length;if(z){for(d=w=p=M=0;M<z;++M)(x=_[M])&&(a=Math.abs(x.value))&&(g+=x.value,N+=a,d+=a*(x.x||0),w+=a*(x.y||0),p+=a*(x.z||0));g*=Math.sqrt(4/z),_.x=d/N,n>1&&(_.y=w/N),n>2&&(_.z=p/N)}else{x=_,x.x=x.data.x,n>1&&(x.y=x.data.y),n>2&&(x.z=x.data.z);do g+=o[x.data.index];while(x=x.next)}_.value=g}function y(_,g,x,a,N){if(!_.value)return!0;var d=[x,a,N][n-1],w=_.x-i.x,p=n>1?_.y-i.y:0,M=n>2?_.z-i.z:0,z=d-g,A=w*w+p*p+M*M;if(z*z/f<A)return A<h&&(w===0&&(w=F(e),A+=w*w),n>1&&p===0&&(p=F(e),A+=p*p),n>2&&M===0&&(M=F(e),A+=M*M),A<u&&(A=Math.sqrt(u*A)),i.vx+=w*_.value*r/A,n>1&&(i.vy+=p*_.value*r/A),n>2&&(i.vz+=M*_.value*r/A)),!0;if(_.length||A>=h)return;(_.data!==i||_.next)&&(w===0&&(w=F(e),A+=w*w),n>1&&p===0&&(p=F(e),A+=p*p),n>2&&M===0&&(M=F(e),A+=M*M),A<u&&(A=Math.sqrt(u*A)));do _.data!==i&&(z=o[_.data.index]*r/A,i.vx+=w*z,n>1&&(i.vy+=p*z),n>2&&(i.vz+=M*z));while(_=_.next)}return l.initialize=function(_,...g){t=_,e=g.find(x=>typeof x=="function")||Math.random,n=g.find(x=>[1,2,3].includes(x))||2,c()},l.strength=function(_){return arguments.length?(s=typeof _=="function"?_:X(+_),c(),l):s},l.distanceMin=function(_){return arguments.length?(u=_*_,l):Math.sqrt(u)},l.distanceMax=function(_){return arguments.length?(h=_*_,l):Math.sqrt(h)},l.theta=function(_){return arguments.length?(f=_*_,l):Math.sqrt(f)},l}let S=null,j=[],nt=0,it=!1;self.onmessage=t=>{const n=t.data;if(n.type==="init"){S&&S.stop(),it=!1,nt=0;const i=n.nodes.length,e=n.params,r=n.initialPositions??{},s=e.dimensions===2?2:3;j=n.nodes.map((h,f)=>{const l=r[h.id];if(l)return{id:h.id,index:f,x:l.x,y:l.y,z:s===2?0:l.z};const c=Math.random()*Math.PI*2,v=e.initialRadius*(.5+Math.random()*.5);if(s===2)return{id:h.id,index:f,x:v*Math.cos(c),y:v*Math.sin(c),z:0};const y=Math.acos(2*Math.random()-1);return{id:h.id,index:f,x:v*Math.sin(y)*Math.cos(c),y:v*Math.sin(y)*Math.sin(c),z:v*Math.cos(y)}});const o=n.links.map(h=>({source:h.source,target:h.target}));S=On(j,s).force("charge",Rn().strength(e.charge).distanceMax(e.distanceMax).theta(e.theta)).force("link",zn(o).id(h=>h.id).distance(e.linkDistance).strength(.2)).force("center",At()).alphaDecay(e.alphaDecay).velocityDecay(e.velocityDecay);const u=n.groups;if(u&&u.length===j.length&&e.clusterStrength>0){const h=e.clusterStrength;S.force("cluster",f=>{const l={},c={},v={},y={};for(let g=0;g<j.length;g++){const x=u[g];x<0||(l[x]=(l[x]??0)+j[g].x,c[x]=(c[x]??0)+j[g].y,v[x]=(v[x]??0)+(j[g].z||0),y[x]=(y[x]??0)+1)}const _=h*f;for(let g=0;g<j.length;g++){const x=u[g];if(x<0||!y[x])continue;const a=j[g];a.vx=(a.vx||0)+(l[x]/y[x]-a.x)*_,a.vy=(a.vy||0)+(c[x]/y[x]-a.y)*_,s===3&&(a.vz=(a.vz||0)+(v[x]/y[x]-a.z)*_)}})}S.on("tick",()=>{nt++;const h=S.alpha();if(nt%e.postEvery!==0&&h>e.settledThreshold)return;const f=new Float32Array(i*3);for(let l=0;l<i;l++)f[l*3]=j[l].x||0,f[l*3+1]=j[l].y||0,f[l*3+2]=s===2?0:j[l].z||0;self.postMessage({type:"positions",positions:f.buffer,alpha:h},[f.buffer]),!it&&h<e.settledThreshold&&(it=!0,self.postMessage({type:"settled"}))})}n.type==="stop"&&S&&(S.stop(),S=null)}})();\n';
|
|
208
261
|
function createLayoutWorker() {
|
|
209
262
|
const blob = new Blob([WORKER_SOURCE], { type: "application/javascript" });
|
|
210
263
|
const url = URL.createObjectURL(blob);
|
|
@@ -1705,6 +1758,7 @@ function applyNodeHighlight(nodesMesh, nodes, selectedNodeId, highlightSet, them
|
|
|
1705
1758
|
const nc = nodes.length;
|
|
1706
1759
|
const tmpColor = new THREE.Color();
|
|
1707
1760
|
const brightTmp = new THREE.Color();
|
|
1761
|
+
const bgColor = new THREE.Color(theme.backgroundColor);
|
|
1708
1762
|
for (let i = 0; i < nc; i++) {
|
|
1709
1763
|
const node = nodes[i];
|
|
1710
1764
|
const baseColor = theme.nodeColor(node.type);
|
|
@@ -1712,13 +1766,17 @@ function applyNodeHighlight(nodesMesh, nodes, selectedNodeId, highlightSet, them
|
|
|
1712
1766
|
if (!highlightSet) {
|
|
1713
1767
|
tmpColor.set(baseColor);
|
|
1714
1768
|
} else if (node.id === selectedNodeId) {
|
|
1715
|
-
|
|
1716
|
-
|
|
1717
|
-
|
|
1718
|
-
|
|
1719
|
-
|
|
1720
|
-
|
|
1721
|
-
|
|
1769
|
+
if (theme.isLight) {
|
|
1770
|
+
tmpColor.set(brightColor);
|
|
1771
|
+
} else {
|
|
1772
|
+
tmpColor.set(brightColor);
|
|
1773
|
+
brightTmp.setRGB(1, 1, 1);
|
|
1774
|
+
tmpColor.lerp(brightTmp, 0.65);
|
|
1775
|
+
tmpColor.multiplyScalar(1.4);
|
|
1776
|
+
tmpColor.r = Math.min(tmpColor.r, 2);
|
|
1777
|
+
tmpColor.g = Math.min(tmpColor.g, 2);
|
|
1778
|
+
tmpColor.b = Math.min(tmpColor.b, 2);
|
|
1779
|
+
}
|
|
1722
1780
|
} else if (highlightSet.has(node.id)) {
|
|
1723
1781
|
const hop = highlightSet.get(node.id);
|
|
1724
1782
|
if (hop === 1) {
|
|
@@ -1730,6 +1788,8 @@ function applyNodeHighlight(nodesMesh, nodes, selectedNodeId, highlightSet, them
|
|
|
1730
1788
|
} else {
|
|
1731
1789
|
tmpColor.set(baseColor).multiplyScalar(0.6);
|
|
1732
1790
|
}
|
|
1791
|
+
} else if (theme.isLight) {
|
|
1792
|
+
tmpColor.set(baseColor).lerp(bgColor, 0.88);
|
|
1733
1793
|
} else {
|
|
1734
1794
|
tmpColor.set(baseColor).multiplyScalar(0.04);
|
|
1735
1795
|
}
|
|
@@ -1747,6 +1807,7 @@ function applyEdgeHighlight(edgesMesh, links, edgeNodeIndices, edgeLinkIndices,
|
|
|
1747
1807
|
const colorArr = colorAttr.array;
|
|
1748
1808
|
const validCount = edgeNodeIndices.length;
|
|
1749
1809
|
const tmpColor = new THREE.Color();
|
|
1810
|
+
const bgColor = new THREE.Color(theme.backgroundColor);
|
|
1750
1811
|
for (let i = 0; i < validCount; i++) {
|
|
1751
1812
|
const origIdx = edgeLinkIndices[i];
|
|
1752
1813
|
const link = links[origIdx];
|
|
@@ -1758,13 +1819,19 @@ function applyEdgeHighlight(edgesMesh, links, edgeNodeIndices, edgeLinkIndices,
|
|
|
1758
1819
|
const maxHopVal = Math.max(highlightSet.get(sId), highlightSet.get(tId));
|
|
1759
1820
|
tmpColor.set(theme.linkColor(link == null ? void 0 : link.type));
|
|
1760
1821
|
if (maxHopVal <= 1) {
|
|
1761
|
-
|
|
1762
|
-
|
|
1763
|
-
|
|
1764
|
-
|
|
1822
|
+
if (theme.isLight) {
|
|
1823
|
+
tmpColor.multiplyScalar(0.55);
|
|
1824
|
+
} else {
|
|
1825
|
+
tmpColor.multiplyScalar(1.8);
|
|
1826
|
+
tmpColor.r = Math.min(tmpColor.r, 1);
|
|
1827
|
+
tmpColor.g = Math.min(tmpColor.g, 1);
|
|
1828
|
+
tmpColor.b = Math.min(tmpColor.b, 1);
|
|
1829
|
+
}
|
|
1765
1830
|
} else if (maxHopVal === 2) {
|
|
1766
|
-
tmpColor.multiplyScalar(1.2);
|
|
1831
|
+
tmpColor.multiplyScalar(theme.isLight ? 0.8 : 1.2);
|
|
1767
1832
|
}
|
|
1833
|
+
} else if (theme.isLight) {
|
|
1834
|
+
tmpColor.set(theme.linkColor(link == null ? void 0 : link.type)).lerp(bgColor, 0.85);
|
|
1768
1835
|
} else {
|
|
1769
1836
|
tmpColor.setRGB(0.01, 0.01, 0.02);
|
|
1770
1837
|
}
|
|
@@ -1894,7 +1961,7 @@ function getOrCreateTexture(cache, nodeId, text, color) {
|
|
|
1894
1961
|
}
|
|
1895
1962
|
return entry;
|
|
1896
1963
|
}
|
|
1897
|
-
function updateLabels(state, nodes, positions, scales, camera, theme, showLabels, labelScale, labelThreshold, maxLabels, labelFormatter, highlightSet) {
|
|
1964
|
+
function updateLabels(state, nodes, positions, scales, camera, theme, showLabels, labelScale, labelThreshold, maxLabels, labelFormatter, highlightSet, hidden) {
|
|
1898
1965
|
if (!positions || nodes.length === 0 || !showLabels) {
|
|
1899
1966
|
for (const sp of state.sprites) sp.visible = false;
|
|
1900
1967
|
return;
|
|
@@ -1908,6 +1975,7 @@ function updateLabels(state, nodes, positions, scales, camera, theme, showLabels
|
|
|
1908
1975
|
const maxDistSq = maxDist * maxDist;
|
|
1909
1976
|
const candidates = [];
|
|
1910
1977
|
for (let i = 0; i < nc; i++) {
|
|
1978
|
+
if (hidden && hidden[i]) continue;
|
|
1911
1979
|
if (highlightSet && !highlightSet.has(nodes[i].id)) continue;
|
|
1912
1980
|
const dx = positions[i * 3] - camPos.x;
|
|
1913
1981
|
const dy = positions[i * 3 + 1] - camPos.y;
|
|
@@ -1984,7 +2052,9 @@ function createOrbitUpdate(camera, controls, keys) {
|
|
|
1984
2052
|
radius = Math.max(controls.minDistance, Math.min(controls.maxDistance, radius));
|
|
1985
2053
|
}
|
|
1986
2054
|
if (azimuth !== 0) {
|
|
1987
|
-
|
|
2055
|
+
const upDot = camera.up.dot(_worldUp);
|
|
2056
|
+
const azSign = upDot < 0 ? -1 : 1;
|
|
2057
|
+
_q.setFromAxisAngle(camera.up, -azimuth * azSign);
|
|
1988
2058
|
_offset.applyQuaternion(_q);
|
|
1989
2059
|
}
|
|
1990
2060
|
if (polar !== 0) {
|
|
@@ -2059,7 +2129,9 @@ function setupKeyboardControls(camera, controls, container, mode = "fly", flySpe
|
|
|
2059
2129
|
container.addEventListener("keydown", onKeyDown2);
|
|
2060
2130
|
container.addEventListener("keyup", onKeyUp);
|
|
2061
2131
|
container.addEventListener("blur", onBlur);
|
|
2062
|
-
|
|
2132
|
+
let enabled = true;
|
|
2133
|
+
const innerUpdate = mode === "fly" ? createFlyUpdate(camera, controls, keys, state) : createOrbitUpdate(camera, controls, keys);
|
|
2134
|
+
const updateFn = () => enabled ? innerUpdate() : false;
|
|
2063
2135
|
function cleanup() {
|
|
2064
2136
|
container.removeEventListener("keydown", onKeyDown2);
|
|
2065
2137
|
container.removeEventListener("keyup", onKeyUp);
|
|
@@ -2068,7 +2140,11 @@ function setupKeyboardControls(camera, controls, container, mode = "fly", flySpe
|
|
|
2068
2140
|
function setFlySpeed(speed) {
|
|
2069
2141
|
state.flySpeed = speed;
|
|
2070
2142
|
}
|
|
2071
|
-
|
|
2143
|
+
function setEnabled(on) {
|
|
2144
|
+
enabled = on;
|
|
2145
|
+
if (!on) for (const k of Object.keys(keys)) keys[k] = false;
|
|
2146
|
+
}
|
|
2147
|
+
return { update: updateFn, cleanup, setFlySpeed, setEnabled };
|
|
2072
2148
|
}
|
|
2073
2149
|
function createScene(container, backgroundColor, style, rendererConfig) {
|
|
2074
2150
|
const scene = new THREE.Scene();
|
|
@@ -2108,8 +2184,10 @@ function createScene(container, backgroundColor, style, rendererConfig) {
|
|
|
2108
2184
|
const cameraMode = (rendererConfig == null ? void 0 : rendererConfig.cameraMode) ?? "fly";
|
|
2109
2185
|
const keyboard = setupKeyboardControls(camera, controls, container, cameraMode, style.flySpeed ?? 1);
|
|
2110
2186
|
controls.enableZoom = false;
|
|
2187
|
+
const flags = { is2D: false };
|
|
2111
2188
|
const _wheelDir = new THREE.Vector3();
|
|
2112
2189
|
const onWheel = (e) => {
|
|
2190
|
+
if (flags.is2D) return;
|
|
2113
2191
|
e.preventDefault();
|
|
2114
2192
|
let delta = -e.deltaY;
|
|
2115
2193
|
if (e.deltaMode === 1) delta *= 40;
|
|
@@ -2133,9 +2211,40 @@ function createScene(container, backgroundColor, style, rendererConfig) {
|
|
|
2133
2211
|
composer: null,
|
|
2134
2212
|
bloomPass: null,
|
|
2135
2213
|
keyboard,
|
|
2136
|
-
scrollCleanup
|
|
2214
|
+
scrollCleanup,
|
|
2215
|
+
flags
|
|
2137
2216
|
};
|
|
2138
2217
|
}
|
|
2218
|
+
function applyCameraMode2D(state, is2D) {
|
|
2219
|
+
const { controls, camera, keyboard } = state;
|
|
2220
|
+
state.flags.is2D = is2D;
|
|
2221
|
+
controls.enableRotate = !is2D;
|
|
2222
|
+
controls.enableZoom = is2D;
|
|
2223
|
+
controls.screenSpacePanning = is2D;
|
|
2224
|
+
keyboard.setEnabled(!is2D);
|
|
2225
|
+
if (is2D) {
|
|
2226
|
+
controls.mouseButtons = {
|
|
2227
|
+
LEFT: THREE.MOUSE.PAN,
|
|
2228
|
+
MIDDLE: THREE.MOUSE.DOLLY,
|
|
2229
|
+
RIGHT: THREE.MOUSE.PAN
|
|
2230
|
+
};
|
|
2231
|
+
controls.touches = { ONE: THREE.TOUCH.PAN, TWO: THREE.TOUCH.DOLLY_PAN };
|
|
2232
|
+
const t = controls.target;
|
|
2233
|
+
const dist = Math.max(camera.position.distanceTo(t), 50);
|
|
2234
|
+
t.z = 0;
|
|
2235
|
+
camera.up.set(0, 1, 0);
|
|
2236
|
+
camera.position.set(t.x, t.y, dist);
|
|
2237
|
+
camera.lookAt(t);
|
|
2238
|
+
} else {
|
|
2239
|
+
controls.mouseButtons = {
|
|
2240
|
+
LEFT: THREE.MOUSE.ROTATE,
|
|
2241
|
+
MIDDLE: THREE.MOUSE.DOLLY,
|
|
2242
|
+
RIGHT: THREE.MOUSE.PAN
|
|
2243
|
+
};
|
|
2244
|
+
controls.touches = { ONE: THREE.TOUCH.ROTATE, TWO: THREE.TOUCH.DOLLY_PAN };
|
|
2245
|
+
}
|
|
2246
|
+
controls.update();
|
|
2247
|
+
}
|
|
2139
2248
|
function initBloom(state, nodeCount, style) {
|
|
2140
2249
|
if (state.composer) return;
|
|
2141
2250
|
try {
|
|
@@ -2332,14 +2441,14 @@ function createNodeMesh(nodes, scales, theme) {
|
|
|
2332
2441
|
mesh.computeBoundingSphere();
|
|
2333
2442
|
return { mesh, material, scales };
|
|
2334
2443
|
}
|
|
2335
|
-
function updateNodePositions(mesh, positions, scales, nodeCount) {
|
|
2444
|
+
function updateNodePositions(mesh, positions, scales, nodeCount, hidden) {
|
|
2336
2445
|
const pos = new THREE.Vector3();
|
|
2337
2446
|
const scale = new THREE.Vector3();
|
|
2338
2447
|
const quat = new THREE.Quaternion();
|
|
2339
2448
|
const mat = new THREE.Matrix4();
|
|
2340
2449
|
for (let i = 0; i < nodeCount; i++) {
|
|
2341
2450
|
pos.set(positions[i * 3], positions[i * 3 + 1], positions[i * 3 + 2]);
|
|
2342
|
-
const sc = scales[i];
|
|
2451
|
+
const sc = hidden && hidden[i] ? 1e-4 : scales[i];
|
|
2343
2452
|
scale.set(sc, sc, sc);
|
|
2344
2453
|
mat.compose(pos, quat, scale);
|
|
2345
2454
|
mesh.setMatrixAt(i, mat);
|
|
@@ -2396,7 +2505,7 @@ function createEdgeMesh(links, edgeNodeIndices, edgeLinkIndices, nodeCount, edge
|
|
|
2396
2505
|
transparent: true,
|
|
2397
2506
|
opacity: adaptiveOpacity,
|
|
2398
2507
|
depthWrite: false,
|
|
2399
|
-
blending: THREE.AdditiveBlending
|
|
2508
|
+
blending: theme.additiveEdges ? THREE.AdditiveBlending : THREE.NormalBlending
|
|
2400
2509
|
});
|
|
2401
2510
|
const mesh = new THREE.LineSegments(geometry, material);
|
|
2402
2511
|
return {
|
|
@@ -2408,10 +2517,19 @@ function createEdgeMesh(links, edgeNodeIndices, edgeLinkIndices, nodeCount, edge
|
|
|
2408
2517
|
edgeLinkIndices
|
|
2409
2518
|
};
|
|
2410
2519
|
}
|
|
2411
|
-
function updateEdgePositions(positionArray, nodePositions, edgeNodeIndices, geometry) {
|
|
2520
|
+
function updateEdgePositions(positionArray, nodePositions, edgeNodeIndices, geometry, hiddenEdges) {
|
|
2412
2521
|
const count = edgeNodeIndices.length;
|
|
2413
2522
|
for (let i = 0; i < count; i++) {
|
|
2414
2523
|
const [si, ti] = edgeNodeIndices[i];
|
|
2524
|
+
if (hiddenEdges && hiddenEdges[i]) {
|
|
2525
|
+
positionArray[i * 6 + 0] = nodePositions[si * 3];
|
|
2526
|
+
positionArray[i * 6 + 1] = nodePositions[si * 3 + 1];
|
|
2527
|
+
positionArray[i * 6 + 2] = nodePositions[si * 3 + 2];
|
|
2528
|
+
positionArray[i * 6 + 3] = nodePositions[si * 3];
|
|
2529
|
+
positionArray[i * 6 + 4] = nodePositions[si * 3 + 1];
|
|
2530
|
+
positionArray[i * 6 + 5] = nodePositions[si * 3 + 2];
|
|
2531
|
+
continue;
|
|
2532
|
+
}
|
|
2415
2533
|
positionArray[i * 6 + 0] = nodePositions[si * 3];
|
|
2416
2534
|
positionArray[i * 6 + 1] = nodePositions[si * 3 + 1];
|
|
2417
2535
|
positionArray[i * 6 + 2] = nodePositions[si * 3 + 2];
|
|
@@ -2474,7 +2592,7 @@ function zoomToFitPositions(camera, controls, positions, duration, padding) {
|
|
|
2474
2592
|
);
|
|
2475
2593
|
}
|
|
2476
2594
|
const EDGE_HIT_THRESHOLD = 5;
|
|
2477
|
-
function setupInteraction(canvas, camera, controls, getNodesMesh, getNodes, callbacks, container, getEdgeData) {
|
|
2595
|
+
function setupInteraction(canvas, camera, controls, getNodesMesh, getNodes, callbacks, container, getEdgeData, options) {
|
|
2478
2596
|
const raycaster = new THREE.Raycaster();
|
|
2479
2597
|
const mouse = new THREE.Vector2();
|
|
2480
2598
|
let mouseDownPos = null;
|
|
@@ -2632,20 +2750,34 @@ function setupInteraction(canvas, camera, controls, getNodesMesh, getNodes, call
|
|
|
2632
2750
|
lastClickTime = now2;
|
|
2633
2751
|
lastClickNodeId = node.id;
|
|
2634
2752
|
singleClickTimer = setTimeout(() => {
|
|
2753
|
+
var _a2, _b;
|
|
2635
2754
|
singleClickTimer = null;
|
|
2636
|
-
const
|
|
2637
|
-
|
|
2638
|
-
|
|
2639
|
-
|
|
2640
|
-
|
|
2641
|
-
|
|
2642
|
-
|
|
2643
|
-
|
|
2644
|
-
|
|
2645
|
-
|
|
2646
|
-
|
|
2647
|
-
|
|
2648
|
-
|
|
2755
|
+
const clickToFocus = ((_a2 = options == null ? void 0 : options.getClickToFocus) == null ? void 0 : _a2.call(options)) ?? true;
|
|
2756
|
+
if (clickToFocus) {
|
|
2757
|
+
const nx = node.x ?? 0;
|
|
2758
|
+
const ny = node.y ?? 0;
|
|
2759
|
+
const nz = node.z ?? 0;
|
|
2760
|
+
if ((_b = options == null ? void 0 : options.getIs2D) == null ? void 0 : _b.call(options)) {
|
|
2761
|
+
animateCamera(
|
|
2762
|
+
camera,
|
|
2763
|
+
controls,
|
|
2764
|
+
{ x: nx, y: ny, z: camera.position.z },
|
|
2765
|
+
{ x: nx, y: ny, z: 0 },
|
|
2766
|
+
800
|
|
2767
|
+
);
|
|
2768
|
+
} else {
|
|
2769
|
+
const dist = Math.hypot(nx, ny, nz);
|
|
2770
|
+
if (dist > 1) {
|
|
2771
|
+
const ratio = 1 + 120 / dist;
|
|
2772
|
+
animateCamera(
|
|
2773
|
+
camera,
|
|
2774
|
+
controls,
|
|
2775
|
+
{ x: nx * ratio, y: ny * ratio, z: nz * ratio },
|
|
2776
|
+
{ x: nx, y: ny, z: nz },
|
|
2777
|
+
1200
|
|
2778
|
+
);
|
|
2779
|
+
}
|
|
2780
|
+
}
|
|
2649
2781
|
}
|
|
2650
2782
|
callbacks.onNodeClick(node);
|
|
2651
2783
|
}, 250);
|
|
@@ -2785,7 +2917,12 @@ function NetworkGraph3DInner(props, ref) {
|
|
|
2785
2917
|
layout: layoutProp,
|
|
2786
2918
|
renderer: rendererProp,
|
|
2787
2919
|
labelFormatter,
|
|
2788
|
-
nodeValueAccessor
|
|
2920
|
+
nodeValueAccessor,
|
|
2921
|
+
visibleNodeIds,
|
|
2922
|
+
linkVisibility,
|
|
2923
|
+
clickToFocus = true,
|
|
2924
|
+
hoverHighlight = false,
|
|
2925
|
+
hoverHighlightHops = 1
|
|
2789
2926
|
} = props;
|
|
2790
2927
|
const containerRef = useRef(null);
|
|
2791
2928
|
const resolvedStyle = useMemo(
|
|
@@ -2822,6 +2959,13 @@ function NetworkGraph3DInner(props, ref) {
|
|
|
2822
2959
|
const selectedNodeIdRef = useRef(selectedNodeId);
|
|
2823
2960
|
const labelFormatterRef = useRef(labelFormatter);
|
|
2824
2961
|
const highlightSetRef = useRef(null);
|
|
2962
|
+
const clickToFocusRef = useRef(clickToFocus);
|
|
2963
|
+
const hoverHighlightRef = useRef(hoverHighlight);
|
|
2964
|
+
const hoverHighlightHopsRef = useRef(hoverHighlightHops);
|
|
2965
|
+
const adjacencyMapRef = useRef(/* @__PURE__ */ new Map());
|
|
2966
|
+
const is2DRef = useRef(false);
|
|
2967
|
+
const hiddenNodesRef = useRef(null);
|
|
2968
|
+
const hiddenEdgesRef = useRef(null);
|
|
2825
2969
|
onNodeClickRef.current = onNodeClick;
|
|
2826
2970
|
onNodeDoubleClickRef.current = onNodeDoubleClick;
|
|
2827
2971
|
onNodeHoverRef.current = onNodeHover;
|
|
@@ -2836,6 +2980,14 @@ function NetworkGraph3DInner(props, ref) {
|
|
|
2836
2980
|
themeRef.current = resolvedTheme;
|
|
2837
2981
|
selectedNodeIdRef.current = selectedNodeId;
|
|
2838
2982
|
labelFormatterRef.current = labelFormatter;
|
|
2983
|
+
clickToFocusRef.current = clickToFocus;
|
|
2984
|
+
hoverHighlightRef.current = hoverHighlight;
|
|
2985
|
+
hoverHighlightHopsRef.current = hoverHighlightHops;
|
|
2986
|
+
const is2D = (layoutProp == null ? void 0 : layoutProp.dimensions) === 2;
|
|
2987
|
+
is2DRef.current = is2D;
|
|
2988
|
+
const layoutKey = JSON.stringify(layoutProp ?? null);
|
|
2989
|
+
const layoutRef = useRef(layoutProp);
|
|
2990
|
+
layoutRef.current = layoutProp;
|
|
2839
2991
|
const mergedData = useMemo(() => {
|
|
2840
2992
|
if (!appendedData) return data;
|
|
2841
2993
|
const existingIds = new Set(data.nodes.map((n) => n.id));
|
|
@@ -2862,6 +3014,11 @@ function NetworkGraph3DInner(props, ref) {
|
|
|
2862
3014
|
() => buildAdjacencyMapFromLinks(mergedData.links),
|
|
2863
3015
|
[mergedData.links]
|
|
2864
3016
|
);
|
|
3017
|
+
adjacencyMapRef.current = adjacencyMap;
|
|
3018
|
+
const visibleSet = useMemo(() => {
|
|
3019
|
+
if (visibleNodeIds == null) return null;
|
|
3020
|
+
return visibleNodeIds instanceof Set ? visibleNodeIds : new Set(visibleNodeIds);
|
|
3021
|
+
}, [visibleNodeIds]);
|
|
2865
3022
|
const highlightSet = useMemo(() => {
|
|
2866
3023
|
if (!selectedNodeId) return null;
|
|
2867
3024
|
return computeHighlightSet(selectedNodeId, adjacencyMap, highlightHops);
|
|
@@ -2875,6 +3032,32 @@ function NetworkGraph3DInner(props, ref) {
|
|
|
2875
3032
|
}
|
|
2876
3033
|
return { min: isFinite(min) ? min : 1, max: isFinite(max) ? max : 1 };
|
|
2877
3034
|
}, [mergedData.nodes, nodeValueAccessor]);
|
|
3035
|
+
const applyHoverHighlight = (node) => {
|
|
3036
|
+
if (!hoverHighlightRef.current) return;
|
|
3037
|
+
if (selectedNodeIdRef.current) return;
|
|
3038
|
+
const gObj = graphObjRef.current;
|
|
3039
|
+
if (!gObj) return;
|
|
3040
|
+
const d = dataRef.current;
|
|
3041
|
+
const set2 = node ? computeHighlightSet(
|
|
3042
|
+
node.id,
|
|
3043
|
+
adjacencyMapRef.current,
|
|
3044
|
+
hoverHighlightHopsRef.current
|
|
3045
|
+
) : null;
|
|
3046
|
+
highlightSetRef.current = set2;
|
|
3047
|
+
applyNodeHighlight(gObj.nodesMesh, d.nodes, (node == null ? void 0 : node.id) ?? null, set2, themeRef.current);
|
|
3048
|
+
applyEdgeHighlight(
|
|
3049
|
+
gObj.edgesMesh,
|
|
3050
|
+
d.links,
|
|
3051
|
+
d.edgeNodeIndices,
|
|
3052
|
+
d.edgeLinkIndices,
|
|
3053
|
+
set2,
|
|
3054
|
+
styleRef.current.edgeOpacity,
|
|
3055
|
+
d.nodes.length,
|
|
3056
|
+
themeRef.current
|
|
3057
|
+
);
|
|
3058
|
+
};
|
|
3059
|
+
const applyHoverHighlightRef = useRef(applyHoverHighlight);
|
|
3060
|
+
applyHoverHighlightRef.current = applyHoverHighlight;
|
|
2878
3061
|
useEffect(() => {
|
|
2879
3062
|
const container = containerRef.current;
|
|
2880
3063
|
if (!container) return;
|
|
@@ -2898,7 +3081,8 @@ function NetworkGraph3DInner(props, ref) {
|
|
|
2898
3081
|
styleRef.current.labelThreshold,
|
|
2899
3082
|
styleRef.current.maxLabels,
|
|
2900
3083
|
labelFormatterRef.current,
|
|
2901
|
-
highlightSetRef.current
|
|
3084
|
+
highlightSetRef.current,
|
|
3085
|
+
hiddenNodesRef.current
|
|
2902
3086
|
);
|
|
2903
3087
|
});
|
|
2904
3088
|
const resizeObserver = setupResize(container, state);
|
|
@@ -2922,7 +3106,8 @@ function NetworkGraph3DInner(props, ref) {
|
|
|
2922
3106
|
},
|
|
2923
3107
|
onNodeHover: (node) => {
|
|
2924
3108
|
var _a;
|
|
2925
|
-
|
|
3109
|
+
(_a = onNodeHoverRef.current) == null ? void 0 : _a.call(onNodeHoverRef, node);
|
|
3110
|
+
applyHoverHighlightRef.current(node);
|
|
2926
3111
|
},
|
|
2927
3112
|
onContextMenu: (node, pos) => {
|
|
2928
3113
|
var _a;
|
|
@@ -2938,6 +3123,7 @@ function NetworkGraph3DInner(props, ref) {
|
|
|
2938
3123
|
},
|
|
2939
3124
|
onNodeDrag: (node, pos) => {
|
|
2940
3125
|
var _a;
|
|
3126
|
+
if (is2DRef.current) pos = { ...pos, z: 0 };
|
|
2941
3127
|
(_a = onNodeDragRef.current) == null ? void 0 : _a.call(onNodeDragRef, node, pos);
|
|
2942
3128
|
const d = dataRef.current;
|
|
2943
3129
|
const idx = d.nodeIdToIndex.get(node.id);
|
|
@@ -2950,7 +3136,13 @@ function NetworkGraph3DInner(props, ref) {
|
|
|
2950
3136
|
node.z = pos.z;
|
|
2951
3137
|
const gObj = graphObjRef.current;
|
|
2952
3138
|
if (gObj && d.scales) {
|
|
2953
|
-
updateNodePositions(
|
|
3139
|
+
updateNodePositions(
|
|
3140
|
+
gObj.nodesMesh,
|
|
3141
|
+
d.positions,
|
|
3142
|
+
d.scales,
|
|
3143
|
+
d.nodes.length,
|
|
3144
|
+
hiddenNodesRef.current
|
|
3145
|
+
);
|
|
2954
3146
|
}
|
|
2955
3147
|
}
|
|
2956
3148
|
},
|
|
@@ -2968,6 +3160,10 @@ function NetworkGraph3DInner(props, ref) {
|
|
|
2968
3160
|
edgeLinkIndices: d.edgeLinkIndices,
|
|
2969
3161
|
positions: d.positions
|
|
2970
3162
|
};
|
|
3163
|
+
},
|
|
3164
|
+
{
|
|
3165
|
+
getClickToFocus: () => clickToFocusRef.current,
|
|
3166
|
+
getIs2D: () => is2DRef.current
|
|
2971
3167
|
}
|
|
2972
3168
|
);
|
|
2973
3169
|
return () => {
|
|
@@ -3114,17 +3310,26 @@ function NetworkGraph3DInner(props, ref) {
|
|
|
3114
3310
|
if (msg.type === "positions") {
|
|
3115
3311
|
const positions = new Float32Array(msg.positions);
|
|
3116
3312
|
dataRef.current.positions = positions;
|
|
3117
|
-
|
|
3313
|
+
const hn = hiddenNodesRef.current;
|
|
3314
|
+
updateNodePositions(
|
|
3315
|
+
nodesMesh,
|
|
3316
|
+
positions,
|
|
3317
|
+
scales,
|
|
3318
|
+
nc,
|
|
3319
|
+
hn && hn.length === nc ? hn : null
|
|
3320
|
+
);
|
|
3118
3321
|
for (let i = 0; i < nc; i++) {
|
|
3119
3322
|
nodes[i].x = positions[i * 3];
|
|
3120
3323
|
nodes[i].y = positions[i * 3 + 1];
|
|
3121
3324
|
nodes[i].z = positions[i * 3 + 2];
|
|
3122
3325
|
}
|
|
3326
|
+
const he = hiddenEdgesRef.current;
|
|
3123
3327
|
updateEdgePositions(
|
|
3124
3328
|
edgeResult.positionArray,
|
|
3125
3329
|
positions,
|
|
3126
3330
|
edgeNodeIndices,
|
|
3127
|
-
edgeResult.geometry
|
|
3331
|
+
edgeResult.geometry,
|
|
3332
|
+
he && he.length === edgeNodeIndices.length ? he : null
|
|
3128
3333
|
);
|
|
3129
3334
|
const selId = selectedNodeIdRef.current;
|
|
3130
3335
|
if (selId && sceneState.selectionRing.visible) {
|
|
@@ -3144,7 +3349,20 @@ function NetworkGraph3DInner(props, ref) {
|
|
|
3144
3349
|
(_b = onLayoutSettledRef.current) == null ? void 0 : _b.call(onLayoutSettledRef);
|
|
3145
3350
|
}
|
|
3146
3351
|
};
|
|
3147
|
-
const
|
|
3352
|
+
const layoutConfig = layoutRef.current;
|
|
3353
|
+
const layoutParams = resolveLayoutParams(nc, layoutConfig);
|
|
3354
|
+
let groups;
|
|
3355
|
+
if (layoutConfig == null ? void 0 : layoutConfig.clusterBy) {
|
|
3356
|
+
const keyOf = (n) => layoutConfig.clusterBy === "type" ? n.type : n.group;
|
|
3357
|
+
const keyToIdx = /* @__PURE__ */ new Map();
|
|
3358
|
+
groups = nodes.map((n) => {
|
|
3359
|
+
const k = keyOf(n);
|
|
3360
|
+
if (k == null) return -1;
|
|
3361
|
+
const ks = String(k);
|
|
3362
|
+
if (!keyToIdx.has(ks)) keyToIdx.set(ks, keyToIdx.size);
|
|
3363
|
+
return keyToIdx.get(ks);
|
|
3364
|
+
});
|
|
3365
|
+
}
|
|
3148
3366
|
worker.postMessage({
|
|
3149
3367
|
type: "init",
|
|
3150
3368
|
nodes: nodes.map((n) => ({ id: n.id })),
|
|
@@ -3153,7 +3371,8 @@ function NetworkGraph3DInner(props, ref) {
|
|
|
3153
3371
|
target: typeof l.target === "object" ? l.target.id : l.target
|
|
3154
3372
|
})),
|
|
3155
3373
|
params: layoutParams,
|
|
3156
|
-
initialPositions: preservedPositionsRef.current
|
|
3374
|
+
initialPositions: preservedPositionsRef.current,
|
|
3375
|
+
groups
|
|
3157
3376
|
});
|
|
3158
3377
|
return () => {
|
|
3159
3378
|
const d = dataRef.current;
|
|
@@ -3178,7 +3397,56 @@ function NetworkGraph3DInner(props, ref) {
|
|
|
3178
3397
|
disposeObject(edgeResult.mesh);
|
|
3179
3398
|
graphObjRef.current = null;
|
|
3180
3399
|
};
|
|
3181
|
-
}, [mergedData, valRange, nodeValueAccessor,
|
|
3400
|
+
}, [mergedData, valRange, nodeValueAccessor, layoutKey]);
|
|
3401
|
+
useEffect(() => {
|
|
3402
|
+
const d = dataRef.current;
|
|
3403
|
+
const gObj = graphObjRef.current;
|
|
3404
|
+
if (!visibleSet && !linkVisibility) {
|
|
3405
|
+
hiddenNodesRef.current = null;
|
|
3406
|
+
hiddenEdgesRef.current = null;
|
|
3407
|
+
} else {
|
|
3408
|
+
const nc = d.nodes.length;
|
|
3409
|
+
const hn = new Uint8Array(nc);
|
|
3410
|
+
if (visibleSet) {
|
|
3411
|
+
for (let i = 0; i < nc; i++) {
|
|
3412
|
+
if (!visibleSet.has(d.nodes[i].id)) hn[i] = 1;
|
|
3413
|
+
}
|
|
3414
|
+
}
|
|
3415
|
+
const ec = d.edgeNodeIndices.length;
|
|
3416
|
+
const he = new Uint8Array(ec);
|
|
3417
|
+
for (let i = 0; i < ec; i++) {
|
|
3418
|
+
const [si, ti] = d.edgeNodeIndices[i];
|
|
3419
|
+
if (hn[si] || hn[ti]) {
|
|
3420
|
+
he[i] = 1;
|
|
3421
|
+
} else if (linkVisibility) {
|
|
3422
|
+
const link = d.links[d.edgeLinkIndices[i]];
|
|
3423
|
+
if (link && !linkVisibility(link)) he[i] = 1;
|
|
3424
|
+
}
|
|
3425
|
+
}
|
|
3426
|
+
hiddenNodesRef.current = visibleSet ? hn : null;
|
|
3427
|
+
hiddenEdgesRef.current = he;
|
|
3428
|
+
}
|
|
3429
|
+
if (gObj && d.positions && d.scales) {
|
|
3430
|
+
updateNodePositions(
|
|
3431
|
+
gObj.nodesMesh,
|
|
3432
|
+
d.positions,
|
|
3433
|
+
d.scales,
|
|
3434
|
+
d.nodes.length,
|
|
3435
|
+
hiddenNodesRef.current
|
|
3436
|
+
);
|
|
3437
|
+
updateEdgePositions(
|
|
3438
|
+
gObj.edgePositionArray,
|
|
3439
|
+
d.positions,
|
|
3440
|
+
d.edgeNodeIndices,
|
|
3441
|
+
gObj.edgeGeometry,
|
|
3442
|
+
hiddenEdgesRef.current
|
|
3443
|
+
);
|
|
3444
|
+
}
|
|
3445
|
+
}, [visibleSet, linkVisibility, mergedData]);
|
|
3446
|
+
useEffect(() => {
|
|
3447
|
+
const s = sceneRef.current;
|
|
3448
|
+
if (s) applyCameraMode2D(s, is2D);
|
|
3449
|
+
}, [is2D]);
|
|
3182
3450
|
useEffect(() => {
|
|
3183
3451
|
const gObj = graphObjRef.current;
|
|
3184
3452
|
const sceneState = sceneRef.current;
|
|
@@ -3246,7 +3514,7 @@ function NetworkGraph3DInner(props, ref) {
|
|
|
3246
3514
|
resolvedStyle.nodeMaxSize
|
|
3247
3515
|
);
|
|
3248
3516
|
dataRef.current.scales = newScales;
|
|
3249
|
-
updateNodePositions(gObj.nodesMesh, positions, newScales, nc);
|
|
3517
|
+
updateNodePositions(gObj.nodesMesh, positions, newScales, nc, hiddenNodesRef.current);
|
|
3250
3518
|
}, [resolvedStyle.nodeMinSize, resolvedStyle.nodeMaxSize, valRange]);
|
|
3251
3519
|
useEffect(() => {
|
|
3252
3520
|
const gObj = graphObjRef.current;
|
|
@@ -3335,6 +3603,17 @@ function NetworkGraph3DInner(props, ref) {
|
|
|
3335
3603
|
const nx = d.positions[idx * 3];
|
|
3336
3604
|
const ny = d.positions[idx * 3 + 1];
|
|
3337
3605
|
const nz = d.positions[idx * 3 + 2];
|
|
3606
|
+
if (is2DRef.current) {
|
|
3607
|
+
const z2 = Math.max(120, Math.min(Math.abs(s.camera.position.z), 500));
|
|
3608
|
+
animateCamera(
|
|
3609
|
+
s.camera,
|
|
3610
|
+
s.controls,
|
|
3611
|
+
{ x: nx, y: ny, z: z2 },
|
|
3612
|
+
{ x: nx, y: ny, z: 0 },
|
|
3613
|
+
duration
|
|
3614
|
+
);
|
|
3615
|
+
return;
|
|
3616
|
+
}
|
|
3338
3617
|
const dist = Math.hypot(nx, ny, nz);
|
|
3339
3618
|
if (dist < 1) return;
|
|
3340
3619
|
const ratio = 1 + 120 / dist;
|
|
@@ -3346,6 +3625,34 @@ function NetworkGraph3DInner(props, ref) {
|
|
|
3346
3625
|
duration
|
|
3347
3626
|
);
|
|
3348
3627
|
},
|
|
3628
|
+
panTo(x2, y2, duration = 600) {
|
|
3629
|
+
const s = sceneRef.current;
|
|
3630
|
+
if (!s) return;
|
|
3631
|
+
const t = s.controls.target;
|
|
3632
|
+
if (is2DRef.current) {
|
|
3633
|
+
animateCamera(
|
|
3634
|
+
s.camera,
|
|
3635
|
+
s.controls,
|
|
3636
|
+
{ x: x2, y: y2, z: s.camera.position.z },
|
|
3637
|
+
{ x: x2, y: y2, z: 0 },
|
|
3638
|
+
duration
|
|
3639
|
+
);
|
|
3640
|
+
} else {
|
|
3641
|
+
const dx = x2 - t.x;
|
|
3642
|
+
const dy = y2 - t.y;
|
|
3643
|
+
animateCamera(
|
|
3644
|
+
s.camera,
|
|
3645
|
+
s.controls,
|
|
3646
|
+
{
|
|
3647
|
+
x: s.camera.position.x + dx,
|
|
3648
|
+
y: s.camera.position.y + dy,
|
|
3649
|
+
z: s.camera.position.z
|
|
3650
|
+
},
|
|
3651
|
+
{ x: x2, y: y2, z: t.z },
|
|
3652
|
+
duration
|
|
3653
|
+
);
|
|
3654
|
+
}
|
|
3655
|
+
},
|
|
3349
3656
|
appendData(newNodes, newLinks) {
|
|
3350
3657
|
if (newNodes.length === 0 && newLinks.length === 0) return 0;
|
|
3351
3658
|
const existingIds = new Set(dataRef.current.nodes.map((n) => n.id));
|
|
@@ -3374,6 +3681,32 @@ function NetworkGraph3DInner(props, ref) {
|
|
|
3374
3681
|
s.renderer.render(s.scene, s.camera);
|
|
3375
3682
|
return s.renderer.domElement.toDataURL("image/png");
|
|
3376
3683
|
},
|
|
3684
|
+
getGraphSnapshot() {
|
|
3685
|
+
var _a;
|
|
3686
|
+
const gObj = graphObjRef.current;
|
|
3687
|
+
const d = dataRef.current;
|
|
3688
|
+
if (!gObj || !d.positions) return null;
|
|
3689
|
+
return {
|
|
3690
|
+
positions: d.positions,
|
|
3691
|
+
count: d.nodes.length,
|
|
3692
|
+
colors: ((_a = gObj.nodesMesh.instanceColor) == null ? void 0 : _a.array) ?? null,
|
|
3693
|
+
hidden: hiddenNodesRef.current,
|
|
3694
|
+
selectedIndex: selectedNodeIdRef.current ? d.nodeIdToIndex.get(selectedNodeIdRef.current) ?? -1 : -1
|
|
3695
|
+
};
|
|
3696
|
+
},
|
|
3697
|
+
getViewportRect() {
|
|
3698
|
+
const s = sceneRef.current;
|
|
3699
|
+
if (!s) return null;
|
|
3700
|
+
const cam = s.camera;
|
|
3701
|
+
const dist = Math.abs(cam.position.z);
|
|
3702
|
+
const halfH = Math.tan(cam.fov * Math.PI / 360) * dist;
|
|
3703
|
+
return {
|
|
3704
|
+
cx: cam.position.x,
|
|
3705
|
+
cy: cam.position.y,
|
|
3706
|
+
halfW: halfH * cam.aspect,
|
|
3707
|
+
halfH
|
|
3708
|
+
};
|
|
3709
|
+
},
|
|
3377
3710
|
reheatLayout() {
|
|
3378
3711
|
const gObj = graphObjRef.current;
|
|
3379
3712
|
if (gObj == null ? void 0 : gObj.worker) {
|
|
@@ -3395,6 +3728,150 @@ function NetworkGraph3DInner(props, ref) {
|
|
|
3395
3728
|
);
|
|
3396
3729
|
}
|
|
3397
3730
|
const NetworkGraph3D = forwardRef(NetworkGraph3DInner);
|
|
3731
|
+
function GraphMinimap({
|
|
3732
|
+
graphRef,
|
|
3733
|
+
width = 200,
|
|
3734
|
+
height = 140,
|
|
3735
|
+
backgroundColor,
|
|
3736
|
+
viewportColor = "#94a3b8",
|
|
3737
|
+
dotRadius = 1.5,
|
|
3738
|
+
fps = 15,
|
|
3739
|
+
padding = 0.08,
|
|
3740
|
+
className,
|
|
3741
|
+
style
|
|
3742
|
+
}) {
|
|
3743
|
+
const canvasRef = useRef(null);
|
|
3744
|
+
const fitRef = useRef(null);
|
|
3745
|
+
const draggingRef = useRef(false);
|
|
3746
|
+
useEffect(() => {
|
|
3747
|
+
const canvas = canvasRef.current;
|
|
3748
|
+
if (!canvas) return;
|
|
3749
|
+
const ctx = canvas.getContext("2d");
|
|
3750
|
+
if (!ctx) return;
|
|
3751
|
+
const dpr = Math.min(window.devicePixelRatio || 1, 2);
|
|
3752
|
+
canvas.width = width * dpr;
|
|
3753
|
+
canvas.height = height * dpr;
|
|
3754
|
+
let raf = 0;
|
|
3755
|
+
let last = 0;
|
|
3756
|
+
const interval2 = 1e3 / fps;
|
|
3757
|
+
const draw = (now2) => {
|
|
3758
|
+
var _a, _b;
|
|
3759
|
+
raf = requestAnimationFrame(draw);
|
|
3760
|
+
if (now2 - last < interval2) return;
|
|
3761
|
+
last = now2;
|
|
3762
|
+
ctx.setTransform(dpr, 0, 0, dpr, 0, 0);
|
|
3763
|
+
ctx.clearRect(0, 0, width, height);
|
|
3764
|
+
if (backgroundColor) {
|
|
3765
|
+
ctx.fillStyle = backgroundColor;
|
|
3766
|
+
ctx.fillRect(0, 0, width, height);
|
|
3767
|
+
}
|
|
3768
|
+
const snap = (_a = graphRef.current) == null ? void 0 : _a.getGraphSnapshot();
|
|
3769
|
+
if (!snap || snap.count === 0) {
|
|
3770
|
+
fitRef.current = null;
|
|
3771
|
+
return;
|
|
3772
|
+
}
|
|
3773
|
+
const { positions, count, colors, hidden, selectedIndex } = snap;
|
|
3774
|
+
let minX = Infinity, maxX = -Infinity, minY = Infinity, maxY = -Infinity;
|
|
3775
|
+
for (let i = 0; i < count; i++) {
|
|
3776
|
+
if (hidden && hidden[i]) continue;
|
|
3777
|
+
const x2 = positions[i * 3];
|
|
3778
|
+
const y2 = positions[i * 3 + 1];
|
|
3779
|
+
if (x2 < minX) minX = x2;
|
|
3780
|
+
if (x2 > maxX) maxX = x2;
|
|
3781
|
+
if (y2 < minY) minY = y2;
|
|
3782
|
+
if (y2 > maxY) maxY = y2;
|
|
3783
|
+
}
|
|
3784
|
+
if (!isFinite(minX)) {
|
|
3785
|
+
fitRef.current = null;
|
|
3786
|
+
return;
|
|
3787
|
+
}
|
|
3788
|
+
const spanX = Math.max(maxX - minX, 1);
|
|
3789
|
+
const spanY = Math.max(maxY - minY, 1);
|
|
3790
|
+
const pad = Math.min(width, height) * padding;
|
|
3791
|
+
const scale = Math.min(
|
|
3792
|
+
(width - pad * 2) / spanX,
|
|
3793
|
+
(height - pad * 2) / spanY
|
|
3794
|
+
);
|
|
3795
|
+
const offsetX = width / 2 - (minX + maxX) / 2 * scale;
|
|
3796
|
+
const offsetY = height / 2 + (minY + maxY) / 2 * scale;
|
|
3797
|
+
fitRef.current = { scale, offsetX, offsetY };
|
|
3798
|
+
const r = dotRadius;
|
|
3799
|
+
for (let i = 0; i < count; i++) {
|
|
3800
|
+
if (hidden && hidden[i]) continue;
|
|
3801
|
+
const cx = positions[i * 3] * scale + offsetX;
|
|
3802
|
+
const cy = -positions[i * 3 + 1] * scale + offsetY;
|
|
3803
|
+
if (colors) {
|
|
3804
|
+
const cr = Math.min(255, Math.round(colors[i * 3] * 255));
|
|
3805
|
+
const cg = Math.min(255, Math.round(colors[i * 3 + 1] * 255));
|
|
3806
|
+
const cb = Math.min(255, Math.round(colors[i * 3 + 2] * 255));
|
|
3807
|
+
ctx.fillStyle = `rgb(${cr},${cg},${cb})`;
|
|
3808
|
+
} else {
|
|
3809
|
+
ctx.fillStyle = viewportColor;
|
|
3810
|
+
}
|
|
3811
|
+
const rad = i === selectedIndex ? r * 2 : r;
|
|
3812
|
+
ctx.beginPath();
|
|
3813
|
+
ctx.arc(cx, cy, rad, 0, Math.PI * 2);
|
|
3814
|
+
ctx.fill();
|
|
3815
|
+
}
|
|
3816
|
+
const vp = (_b = graphRef.current) == null ? void 0 : _b.getViewportRect();
|
|
3817
|
+
if (vp) {
|
|
3818
|
+
const x2 = (vp.cx - vp.halfW) * scale + offsetX;
|
|
3819
|
+
const y2 = -(vp.cy + vp.halfH) * scale + offsetY;
|
|
3820
|
+
const w = vp.halfW * 2 * scale;
|
|
3821
|
+
const h = vp.halfH * 2 * scale;
|
|
3822
|
+
ctx.strokeStyle = viewportColor;
|
|
3823
|
+
ctx.lineWidth = 1;
|
|
3824
|
+
ctx.strokeRect(x2, y2, w, h);
|
|
3825
|
+
ctx.fillStyle = viewportColor + "1a";
|
|
3826
|
+
ctx.fillRect(x2, y2, w, h);
|
|
3827
|
+
}
|
|
3828
|
+
};
|
|
3829
|
+
raf = requestAnimationFrame(draw);
|
|
3830
|
+
return () => cancelAnimationFrame(raf);
|
|
3831
|
+
}, [graphRef, width, height, backgroundColor, viewportColor, dotRadius, fps, padding]);
|
|
3832
|
+
const panToPointer = (e) => {
|
|
3833
|
+
var _a;
|
|
3834
|
+
const fit = fitRef.current;
|
|
3835
|
+
const canvas = canvasRef.current;
|
|
3836
|
+
if (!fit || !canvas) return;
|
|
3837
|
+
const rect = canvas.getBoundingClientRect();
|
|
3838
|
+
const px = e.clientX - rect.left;
|
|
3839
|
+
const py = e.clientY - rect.top;
|
|
3840
|
+
const wx = (px - fit.offsetX) / fit.scale;
|
|
3841
|
+
const wy = -(py - fit.offsetY) / fit.scale;
|
|
3842
|
+
(_a = graphRef.current) == null ? void 0 : _a.panTo(wx, wy, draggingRef.current ? 0 : 300);
|
|
3843
|
+
};
|
|
3844
|
+
return /* @__PURE__ */ jsx(
|
|
3845
|
+
"canvas",
|
|
3846
|
+
{
|
|
3847
|
+
ref: canvasRef,
|
|
3848
|
+
className,
|
|
3849
|
+
style: {
|
|
3850
|
+
width,
|
|
3851
|
+
height,
|
|
3852
|
+
cursor: "pointer",
|
|
3853
|
+
touchAction: "none",
|
|
3854
|
+
display: "block",
|
|
3855
|
+
...style
|
|
3856
|
+
},
|
|
3857
|
+
onPointerDown: (e) => {
|
|
3858
|
+
draggingRef.current = true;
|
|
3859
|
+
e.currentTarget.setPointerCapture(e.pointerId);
|
|
3860
|
+
panToPointer(e);
|
|
3861
|
+
},
|
|
3862
|
+
onPointerMove: (e) => {
|
|
3863
|
+
if (draggingRef.current) panToPointer(e);
|
|
3864
|
+
},
|
|
3865
|
+
onPointerUp: (e) => {
|
|
3866
|
+
draggingRef.current = false;
|
|
3867
|
+
e.currentTarget.releasePointerCapture(e.pointerId);
|
|
3868
|
+
},
|
|
3869
|
+
onPointerCancel: () => {
|
|
3870
|
+
draggingRef.current = false;
|
|
3871
|
+
}
|
|
3872
|
+
}
|
|
3873
|
+
);
|
|
3874
|
+
}
|
|
3398
3875
|
function forceCenter(x2, y2, z2) {
|
|
3399
3876
|
var nodes, strength = 1;
|
|
3400
3877
|
if (x2 == null) x2 = 0;
|
|
@@ -5463,6 +5940,7 @@ function CtrlBtn({ children, title, onClick }) {
|
|
|
5463
5940
|
export {
|
|
5464
5941
|
DEFAULT_LAYOUT,
|
|
5465
5942
|
DEFAULT_STYLE,
|
|
5943
|
+
GraphMinimap,
|
|
5466
5944
|
NetworkGraph3D,
|
|
5467
5945
|
NodeDetailPanel,
|
|
5468
5946
|
SubgraphView2D,
|
|
@@ -5473,6 +5951,7 @@ export {
|
|
|
5473
5951
|
computeHighlightSet,
|
|
5474
5952
|
minimal,
|
|
5475
5953
|
neon,
|
|
5954
|
+
paper,
|
|
5476
5955
|
resolveTheme,
|
|
5477
5956
|
zoomToFitPositions
|
|
5478
5957
|
};
|