@cocorof/graphier 1.3.3 → 1.4.1
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 +585 -51
- package/dist/index.cjs.map +1 -1
- package/dist/index.d.ts +104 -0
- package/dist/index.js +585 -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;
|
|
@@ -1963,6 +2031,45 @@ const _right = new THREE.Vector3();
|
|
|
1963
2031
|
const _q = new THREE.Quaternion();
|
|
1964
2032
|
const _dir = new THREE.Vector3();
|
|
1965
2033
|
const _worldUp = new THREE.Vector3(0, 1, 0);
|
|
2034
|
+
const PAN_SPEED = 0.02;
|
|
2035
|
+
const PAN_ZOOM_FACTOR = 0.02;
|
|
2036
|
+
function createPanUpdate(camera, controls, keys) {
|
|
2037
|
+
const _panRight = new THREE.Vector3();
|
|
2038
|
+
const _panUp = new THREE.Vector3();
|
|
2039
|
+
const _panOffset = new THREE.Vector3();
|
|
2040
|
+
return function update() {
|
|
2041
|
+
let dx = 0;
|
|
2042
|
+
let dy = 0;
|
|
2043
|
+
if (keys["ArrowLeft"] || keys["a"] || keys["A"]) dx -= 1;
|
|
2044
|
+
if (keys["ArrowRight"] || keys["d"] || keys["D"]) dx += 1;
|
|
2045
|
+
if (keys["ArrowUp"] || keys["w"] || keys["W"]) dy += 1;
|
|
2046
|
+
if (keys["ArrowDown"] || keys["s"] || keys["S"]) dy -= 1;
|
|
2047
|
+
const zoomIn = keys["z"] || keys["Z"] || keys["+"] || keys["="];
|
|
2048
|
+
const zoomOut = keys["x"] || keys["X"] || keys["-"] || keys["_"];
|
|
2049
|
+
if (!dx && !dy && !zoomIn && !zoomOut) return false;
|
|
2050
|
+
const target = controls.target;
|
|
2051
|
+
const dist = camera.position.distanceTo(target);
|
|
2052
|
+
if (dx || dy) {
|
|
2053
|
+
const step = Math.max(dist, 50) * PAN_SPEED;
|
|
2054
|
+
_panRight.setFromMatrixColumn(camera.matrix, 0);
|
|
2055
|
+
_panUp.setFromMatrixColumn(camera.matrix, 1);
|
|
2056
|
+
_panOffset.set(0, 0, 0).addScaledVector(_panRight, dx * step).addScaledVector(_panUp, dy * step);
|
|
2057
|
+
camera.position.add(_panOffset);
|
|
2058
|
+
target.add(_panOffset);
|
|
2059
|
+
}
|
|
2060
|
+
if (zoomIn || zoomOut) {
|
|
2061
|
+
const factor = zoomIn ? -PAN_ZOOM_FACTOR : PAN_ZOOM_FACTOR;
|
|
2062
|
+
_panOffset.copy(camera.position).sub(target);
|
|
2063
|
+
const newLen = Math.max(
|
|
2064
|
+
controls.minDistance,
|
|
2065
|
+
Math.min(controls.maxDistance, _panOffset.length() * (1 + factor))
|
|
2066
|
+
);
|
|
2067
|
+
_panOffset.setLength(newLen);
|
|
2068
|
+
camera.position.copy(target).add(_panOffset);
|
|
2069
|
+
}
|
|
2070
|
+
return true;
|
|
2071
|
+
};
|
|
2072
|
+
}
|
|
1966
2073
|
function createOrbitUpdate(camera, controls, keys) {
|
|
1967
2074
|
return function update() {
|
|
1968
2075
|
let zoom = 0;
|
|
@@ -2061,7 +2168,14 @@ function setupKeyboardControls(camera, controls, container, mode = "fly", flySpe
|
|
|
2061
2168
|
container.addEventListener("keydown", onKeyDown2);
|
|
2062
2169
|
container.addEventListener("keyup", onKeyUp);
|
|
2063
2170
|
container.addEventListener("blur", onBlur);
|
|
2064
|
-
|
|
2171
|
+
let enabled = true;
|
|
2172
|
+
let currentMode = mode;
|
|
2173
|
+
const updaters = {
|
|
2174
|
+
fly: createFlyUpdate(camera, controls, keys, state),
|
|
2175
|
+
orbit: createOrbitUpdate(camera, controls, keys),
|
|
2176
|
+
pan: createPanUpdate(camera, controls, keys)
|
|
2177
|
+
};
|
|
2178
|
+
const updateFn = () => enabled ? updaters[currentMode]() : false;
|
|
2065
2179
|
function cleanup() {
|
|
2066
2180
|
container.removeEventListener("keydown", onKeyDown2);
|
|
2067
2181
|
container.removeEventListener("keyup", onKeyUp);
|
|
@@ -2070,7 +2184,15 @@ function setupKeyboardControls(camera, controls, container, mode = "fly", flySpe
|
|
|
2070
2184
|
function setFlySpeed(speed) {
|
|
2071
2185
|
state.flySpeed = speed;
|
|
2072
2186
|
}
|
|
2073
|
-
|
|
2187
|
+
function setEnabled(on) {
|
|
2188
|
+
enabled = on;
|
|
2189
|
+
if (!on) for (const k of Object.keys(keys)) keys[k] = false;
|
|
2190
|
+
}
|
|
2191
|
+
function setMode(m2) {
|
|
2192
|
+
currentMode = m2;
|
|
2193
|
+
for (const k of Object.keys(keys)) keys[k] = false;
|
|
2194
|
+
}
|
|
2195
|
+
return { update: updateFn, cleanup, setFlySpeed, setEnabled, setMode };
|
|
2074
2196
|
}
|
|
2075
2197
|
function createScene(container, backgroundColor, style, rendererConfig) {
|
|
2076
2198
|
const scene = new THREE.Scene();
|
|
@@ -2110,8 +2232,13 @@ function createScene(container, backgroundColor, style, rendererConfig) {
|
|
|
2110
2232
|
const cameraMode = (rendererConfig == null ? void 0 : rendererConfig.cameraMode) ?? "fly";
|
|
2111
2233
|
const keyboard = setupKeyboardControls(camera, controls, container, cameraMode, style.flySpeed ?? 1);
|
|
2112
2234
|
controls.enableZoom = false;
|
|
2235
|
+
const flags = {
|
|
2236
|
+
is2D: false,
|
|
2237
|
+
keyboardMode3D: cameraMode
|
|
2238
|
+
};
|
|
2113
2239
|
const _wheelDir = new THREE.Vector3();
|
|
2114
2240
|
const onWheel = (e) => {
|
|
2241
|
+
if (flags.is2D) return;
|
|
2115
2242
|
e.preventDefault();
|
|
2116
2243
|
let delta = -e.deltaY;
|
|
2117
2244
|
if (e.deltaMode === 1) delta *= 40;
|
|
@@ -2135,9 +2262,41 @@ function createScene(container, backgroundColor, style, rendererConfig) {
|
|
|
2135
2262
|
composer: null,
|
|
2136
2263
|
bloomPass: null,
|
|
2137
2264
|
keyboard,
|
|
2138
|
-
scrollCleanup
|
|
2265
|
+
scrollCleanup,
|
|
2266
|
+
flags
|
|
2139
2267
|
};
|
|
2140
2268
|
}
|
|
2269
|
+
function applyCameraMode2D(state, is2D) {
|
|
2270
|
+
const { controls, camera, keyboard } = state;
|
|
2271
|
+
state.flags.is2D = is2D;
|
|
2272
|
+
controls.enableRotate = true;
|
|
2273
|
+
controls.enableZoom = is2D;
|
|
2274
|
+
controls.screenSpacePanning = is2D;
|
|
2275
|
+
keyboard.setEnabled(true);
|
|
2276
|
+
keyboard.setMode(is2D ? "pan" : state.flags.keyboardMode3D);
|
|
2277
|
+
if (is2D) {
|
|
2278
|
+
controls.mouseButtons = {
|
|
2279
|
+
LEFT: THREE.MOUSE.PAN,
|
|
2280
|
+
MIDDLE: THREE.MOUSE.DOLLY,
|
|
2281
|
+
RIGHT: THREE.MOUSE.ROTATE
|
|
2282
|
+
};
|
|
2283
|
+
controls.touches = { ONE: THREE.TOUCH.PAN, TWO: THREE.TOUCH.DOLLY_PAN };
|
|
2284
|
+
const t = controls.target;
|
|
2285
|
+
const dist = Math.max(camera.position.distanceTo(t), 50);
|
|
2286
|
+
t.z = 0;
|
|
2287
|
+
camera.up.set(0, 1, 0);
|
|
2288
|
+
camera.position.set(t.x, t.y, dist);
|
|
2289
|
+
camera.lookAt(t);
|
|
2290
|
+
} else {
|
|
2291
|
+
controls.mouseButtons = {
|
|
2292
|
+
LEFT: THREE.MOUSE.ROTATE,
|
|
2293
|
+
MIDDLE: THREE.MOUSE.DOLLY,
|
|
2294
|
+
RIGHT: THREE.MOUSE.PAN
|
|
2295
|
+
};
|
|
2296
|
+
controls.touches = { ONE: THREE.TOUCH.ROTATE, TWO: THREE.TOUCH.DOLLY_PAN };
|
|
2297
|
+
}
|
|
2298
|
+
controls.update();
|
|
2299
|
+
}
|
|
2141
2300
|
function initBloom(state, nodeCount, style) {
|
|
2142
2301
|
if (state.composer) return;
|
|
2143
2302
|
try {
|
|
@@ -2334,14 +2493,14 @@ function createNodeMesh(nodes, scales, theme) {
|
|
|
2334
2493
|
mesh.computeBoundingSphere();
|
|
2335
2494
|
return { mesh, material, scales };
|
|
2336
2495
|
}
|
|
2337
|
-
function updateNodePositions(mesh, positions, scales, nodeCount) {
|
|
2496
|
+
function updateNodePositions(mesh, positions, scales, nodeCount, hidden) {
|
|
2338
2497
|
const pos = new THREE.Vector3();
|
|
2339
2498
|
const scale = new THREE.Vector3();
|
|
2340
2499
|
const quat = new THREE.Quaternion();
|
|
2341
2500
|
const mat = new THREE.Matrix4();
|
|
2342
2501
|
for (let i = 0; i < nodeCount; i++) {
|
|
2343
2502
|
pos.set(positions[i * 3], positions[i * 3 + 1], positions[i * 3 + 2]);
|
|
2344
|
-
const sc = scales[i];
|
|
2503
|
+
const sc = hidden && hidden[i] ? 1e-4 : scales[i];
|
|
2345
2504
|
scale.set(sc, sc, sc);
|
|
2346
2505
|
mat.compose(pos, quat, scale);
|
|
2347
2506
|
mesh.setMatrixAt(i, mat);
|
|
@@ -2398,7 +2557,7 @@ function createEdgeMesh(links, edgeNodeIndices, edgeLinkIndices, nodeCount, edge
|
|
|
2398
2557
|
transparent: true,
|
|
2399
2558
|
opacity: adaptiveOpacity,
|
|
2400
2559
|
depthWrite: false,
|
|
2401
|
-
blending: THREE.AdditiveBlending
|
|
2560
|
+
blending: theme.additiveEdges ? THREE.AdditiveBlending : THREE.NormalBlending
|
|
2402
2561
|
});
|
|
2403
2562
|
const mesh = new THREE.LineSegments(geometry, material);
|
|
2404
2563
|
return {
|
|
@@ -2410,10 +2569,19 @@ function createEdgeMesh(links, edgeNodeIndices, edgeLinkIndices, nodeCount, edge
|
|
|
2410
2569
|
edgeLinkIndices
|
|
2411
2570
|
};
|
|
2412
2571
|
}
|
|
2413
|
-
function updateEdgePositions(positionArray, nodePositions, edgeNodeIndices, geometry) {
|
|
2572
|
+
function updateEdgePositions(positionArray, nodePositions, edgeNodeIndices, geometry, hiddenEdges) {
|
|
2414
2573
|
const count = edgeNodeIndices.length;
|
|
2415
2574
|
for (let i = 0; i < count; i++) {
|
|
2416
2575
|
const [si, ti] = edgeNodeIndices[i];
|
|
2576
|
+
if (hiddenEdges && hiddenEdges[i]) {
|
|
2577
|
+
positionArray[i * 6 + 0] = nodePositions[si * 3];
|
|
2578
|
+
positionArray[i * 6 + 1] = nodePositions[si * 3 + 1];
|
|
2579
|
+
positionArray[i * 6 + 2] = nodePositions[si * 3 + 2];
|
|
2580
|
+
positionArray[i * 6 + 3] = nodePositions[si * 3];
|
|
2581
|
+
positionArray[i * 6 + 4] = nodePositions[si * 3 + 1];
|
|
2582
|
+
positionArray[i * 6 + 5] = nodePositions[si * 3 + 2];
|
|
2583
|
+
continue;
|
|
2584
|
+
}
|
|
2417
2585
|
positionArray[i * 6 + 0] = nodePositions[si * 3];
|
|
2418
2586
|
positionArray[i * 6 + 1] = nodePositions[si * 3 + 1];
|
|
2419
2587
|
positionArray[i * 6 + 2] = nodePositions[si * 3 + 2];
|
|
@@ -2476,7 +2644,7 @@ function zoomToFitPositions(camera, controls, positions, duration, padding) {
|
|
|
2476
2644
|
);
|
|
2477
2645
|
}
|
|
2478
2646
|
const EDGE_HIT_THRESHOLD = 5;
|
|
2479
|
-
function setupInteraction(canvas, camera, controls, getNodesMesh, getNodes, callbacks, container, getEdgeData) {
|
|
2647
|
+
function setupInteraction(canvas, camera, controls, getNodesMesh, getNodes, callbacks, container, getEdgeData, options) {
|
|
2480
2648
|
const raycaster = new THREE.Raycaster();
|
|
2481
2649
|
const mouse = new THREE.Vector2();
|
|
2482
2650
|
let mouseDownPos = null;
|
|
@@ -2488,11 +2656,12 @@ function setupInteraction(canvas, camera, controls, getNodesMesh, getNodes, call
|
|
|
2488
2656
|
const dragPlane = new THREE.Plane();
|
|
2489
2657
|
const dragIntersect = new THREE.Vector3();
|
|
2490
2658
|
function onPointerDown2(e) {
|
|
2659
|
+
var _a;
|
|
2491
2660
|
mouseDownPos = { x: e.clientX, y: e.clientY };
|
|
2492
2661
|
if (container && document.activeElement !== container) {
|
|
2493
2662
|
container.focus({ preventScroll: true });
|
|
2494
2663
|
}
|
|
2495
|
-
if (callbacks.onNodeDrag) {
|
|
2664
|
+
if (callbacks.onNodeDrag && (((_a = options == null ? void 0 : options.getNodeDragEnabled) == null ? void 0 : _a.call(options)) ?? true)) {
|
|
2496
2665
|
const nodesMesh = getNodesMesh();
|
|
2497
2666
|
if (nodesMesh) {
|
|
2498
2667
|
const rect = canvas.getBoundingClientRect();
|
|
@@ -2634,20 +2803,34 @@ function setupInteraction(canvas, camera, controls, getNodesMesh, getNodes, call
|
|
|
2634
2803
|
lastClickTime = now2;
|
|
2635
2804
|
lastClickNodeId = node.id;
|
|
2636
2805
|
singleClickTimer = setTimeout(() => {
|
|
2806
|
+
var _a2, _b;
|
|
2637
2807
|
singleClickTimer = null;
|
|
2638
|
-
const
|
|
2639
|
-
|
|
2640
|
-
|
|
2641
|
-
|
|
2642
|
-
|
|
2643
|
-
|
|
2644
|
-
|
|
2645
|
-
|
|
2646
|
-
|
|
2647
|
-
|
|
2648
|
-
|
|
2649
|
-
|
|
2650
|
-
|
|
2808
|
+
const clickToFocus = ((_a2 = options == null ? void 0 : options.getClickToFocus) == null ? void 0 : _a2.call(options)) ?? true;
|
|
2809
|
+
if (clickToFocus) {
|
|
2810
|
+
const nx = node.x ?? 0;
|
|
2811
|
+
const ny = node.y ?? 0;
|
|
2812
|
+
const nz = node.z ?? 0;
|
|
2813
|
+
if ((_b = options == null ? void 0 : options.getIs2D) == null ? void 0 : _b.call(options)) {
|
|
2814
|
+
animateCamera(
|
|
2815
|
+
camera,
|
|
2816
|
+
controls,
|
|
2817
|
+
{ x: nx, y: ny, z: camera.position.z },
|
|
2818
|
+
{ x: nx, y: ny, z: 0 },
|
|
2819
|
+
800
|
|
2820
|
+
);
|
|
2821
|
+
} else {
|
|
2822
|
+
const dist = Math.hypot(nx, ny, nz);
|
|
2823
|
+
if (dist > 1) {
|
|
2824
|
+
const ratio = 1 + 120 / dist;
|
|
2825
|
+
animateCamera(
|
|
2826
|
+
camera,
|
|
2827
|
+
controls,
|
|
2828
|
+
{ x: nx * ratio, y: ny * ratio, z: nz * ratio },
|
|
2829
|
+
{ x: nx, y: ny, z: nz },
|
|
2830
|
+
1200
|
|
2831
|
+
);
|
|
2832
|
+
}
|
|
2833
|
+
}
|
|
2651
2834
|
}
|
|
2652
2835
|
callbacks.onNodeClick(node);
|
|
2653
2836
|
}, 250);
|
|
@@ -2787,7 +2970,13 @@ function NetworkGraph3DInner(props, ref) {
|
|
|
2787
2970
|
layout: layoutProp,
|
|
2788
2971
|
renderer: rendererProp,
|
|
2789
2972
|
labelFormatter,
|
|
2790
|
-
nodeValueAccessor
|
|
2973
|
+
nodeValueAccessor,
|
|
2974
|
+
visibleNodeIds,
|
|
2975
|
+
linkVisibility,
|
|
2976
|
+
enableNodeDrag = true,
|
|
2977
|
+
clickToFocus = true,
|
|
2978
|
+
hoverHighlight = false,
|
|
2979
|
+
hoverHighlightHops = 1
|
|
2791
2980
|
} = props;
|
|
2792
2981
|
const containerRef = useRef(null);
|
|
2793
2982
|
const resolvedStyle = useMemo(
|
|
@@ -2824,6 +3013,14 @@ function NetworkGraph3DInner(props, ref) {
|
|
|
2824
3013
|
const selectedNodeIdRef = useRef(selectedNodeId);
|
|
2825
3014
|
const labelFormatterRef = useRef(labelFormatter);
|
|
2826
3015
|
const highlightSetRef = useRef(null);
|
|
3016
|
+
const clickToFocusRef = useRef(clickToFocus);
|
|
3017
|
+
const enableNodeDragRef = useRef(enableNodeDrag);
|
|
3018
|
+
const hoverHighlightRef = useRef(hoverHighlight);
|
|
3019
|
+
const hoverHighlightHopsRef = useRef(hoverHighlightHops);
|
|
3020
|
+
const adjacencyMapRef = useRef(/* @__PURE__ */ new Map());
|
|
3021
|
+
const is2DRef = useRef(false);
|
|
3022
|
+
const hiddenNodesRef = useRef(null);
|
|
3023
|
+
const hiddenEdgesRef = useRef(null);
|
|
2827
3024
|
onNodeClickRef.current = onNodeClick;
|
|
2828
3025
|
onNodeDoubleClickRef.current = onNodeDoubleClick;
|
|
2829
3026
|
onNodeHoverRef.current = onNodeHover;
|
|
@@ -2838,6 +3035,15 @@ function NetworkGraph3DInner(props, ref) {
|
|
|
2838
3035
|
themeRef.current = resolvedTheme;
|
|
2839
3036
|
selectedNodeIdRef.current = selectedNodeId;
|
|
2840
3037
|
labelFormatterRef.current = labelFormatter;
|
|
3038
|
+
clickToFocusRef.current = clickToFocus;
|
|
3039
|
+
enableNodeDragRef.current = enableNodeDrag;
|
|
3040
|
+
hoverHighlightRef.current = hoverHighlight;
|
|
3041
|
+
hoverHighlightHopsRef.current = hoverHighlightHops;
|
|
3042
|
+
const is2D = (layoutProp == null ? void 0 : layoutProp.dimensions) === 2;
|
|
3043
|
+
is2DRef.current = is2D;
|
|
3044
|
+
const layoutKey = JSON.stringify(layoutProp ?? null);
|
|
3045
|
+
const layoutRef = useRef(layoutProp);
|
|
3046
|
+
layoutRef.current = layoutProp;
|
|
2841
3047
|
const mergedData = useMemo(() => {
|
|
2842
3048
|
if (!appendedData) return data;
|
|
2843
3049
|
const existingIds = new Set(data.nodes.map((n) => n.id));
|
|
@@ -2864,6 +3070,11 @@ function NetworkGraph3DInner(props, ref) {
|
|
|
2864
3070
|
() => buildAdjacencyMapFromLinks(mergedData.links),
|
|
2865
3071
|
[mergedData.links]
|
|
2866
3072
|
);
|
|
3073
|
+
adjacencyMapRef.current = adjacencyMap;
|
|
3074
|
+
const visibleSet = useMemo(() => {
|
|
3075
|
+
if (visibleNodeIds == null) return null;
|
|
3076
|
+
return visibleNodeIds instanceof Set ? visibleNodeIds : new Set(visibleNodeIds);
|
|
3077
|
+
}, [visibleNodeIds]);
|
|
2867
3078
|
const highlightSet = useMemo(() => {
|
|
2868
3079
|
if (!selectedNodeId) return null;
|
|
2869
3080
|
return computeHighlightSet(selectedNodeId, adjacencyMap, highlightHops);
|
|
@@ -2877,6 +3088,32 @@ function NetworkGraph3DInner(props, ref) {
|
|
|
2877
3088
|
}
|
|
2878
3089
|
return { min: isFinite(min) ? min : 1, max: isFinite(max) ? max : 1 };
|
|
2879
3090
|
}, [mergedData.nodes, nodeValueAccessor]);
|
|
3091
|
+
const applyHoverHighlight = (node) => {
|
|
3092
|
+
if (!hoverHighlightRef.current) return;
|
|
3093
|
+
if (selectedNodeIdRef.current) return;
|
|
3094
|
+
const gObj = graphObjRef.current;
|
|
3095
|
+
if (!gObj) return;
|
|
3096
|
+
const d = dataRef.current;
|
|
3097
|
+
const set2 = node ? computeHighlightSet(
|
|
3098
|
+
node.id,
|
|
3099
|
+
adjacencyMapRef.current,
|
|
3100
|
+
hoverHighlightHopsRef.current
|
|
3101
|
+
) : null;
|
|
3102
|
+
highlightSetRef.current = set2;
|
|
3103
|
+
applyNodeHighlight(gObj.nodesMesh, d.nodes, (node == null ? void 0 : node.id) ?? null, set2, themeRef.current);
|
|
3104
|
+
applyEdgeHighlight(
|
|
3105
|
+
gObj.edgesMesh,
|
|
3106
|
+
d.links,
|
|
3107
|
+
d.edgeNodeIndices,
|
|
3108
|
+
d.edgeLinkIndices,
|
|
3109
|
+
set2,
|
|
3110
|
+
styleRef.current.edgeOpacity,
|
|
3111
|
+
d.nodes.length,
|
|
3112
|
+
themeRef.current
|
|
3113
|
+
);
|
|
3114
|
+
};
|
|
3115
|
+
const applyHoverHighlightRef = useRef(applyHoverHighlight);
|
|
3116
|
+
applyHoverHighlightRef.current = applyHoverHighlight;
|
|
2880
3117
|
useEffect(() => {
|
|
2881
3118
|
const container = containerRef.current;
|
|
2882
3119
|
if (!container) return;
|
|
@@ -2900,7 +3137,8 @@ function NetworkGraph3DInner(props, ref) {
|
|
|
2900
3137
|
styleRef.current.labelThreshold,
|
|
2901
3138
|
styleRef.current.maxLabels,
|
|
2902
3139
|
labelFormatterRef.current,
|
|
2903
|
-
highlightSetRef.current
|
|
3140
|
+
highlightSetRef.current,
|
|
3141
|
+
hiddenNodesRef.current
|
|
2904
3142
|
);
|
|
2905
3143
|
});
|
|
2906
3144
|
const resizeObserver = setupResize(container, state);
|
|
@@ -2924,7 +3162,8 @@ function NetworkGraph3DInner(props, ref) {
|
|
|
2924
3162
|
},
|
|
2925
3163
|
onNodeHover: (node) => {
|
|
2926
3164
|
var _a;
|
|
2927
|
-
|
|
3165
|
+
(_a = onNodeHoverRef.current) == null ? void 0 : _a.call(onNodeHoverRef, node);
|
|
3166
|
+
applyHoverHighlightRef.current(node);
|
|
2928
3167
|
},
|
|
2929
3168
|
onContextMenu: (node, pos) => {
|
|
2930
3169
|
var _a;
|
|
@@ -2940,6 +3179,7 @@ function NetworkGraph3DInner(props, ref) {
|
|
|
2940
3179
|
},
|
|
2941
3180
|
onNodeDrag: (node, pos) => {
|
|
2942
3181
|
var _a;
|
|
3182
|
+
if (is2DRef.current) pos = { ...pos, z: 0 };
|
|
2943
3183
|
(_a = onNodeDragRef.current) == null ? void 0 : _a.call(onNodeDragRef, node, pos);
|
|
2944
3184
|
const d = dataRef.current;
|
|
2945
3185
|
const idx = d.nodeIdToIndex.get(node.id);
|
|
@@ -2952,7 +3192,13 @@ function NetworkGraph3DInner(props, ref) {
|
|
|
2952
3192
|
node.z = pos.z;
|
|
2953
3193
|
const gObj = graphObjRef.current;
|
|
2954
3194
|
if (gObj && d.scales) {
|
|
2955
|
-
updateNodePositions(
|
|
3195
|
+
updateNodePositions(
|
|
3196
|
+
gObj.nodesMesh,
|
|
3197
|
+
d.positions,
|
|
3198
|
+
d.scales,
|
|
3199
|
+
d.nodes.length,
|
|
3200
|
+
hiddenNodesRef.current
|
|
3201
|
+
);
|
|
2956
3202
|
}
|
|
2957
3203
|
}
|
|
2958
3204
|
},
|
|
@@ -2970,6 +3216,11 @@ function NetworkGraph3DInner(props, ref) {
|
|
|
2970
3216
|
edgeLinkIndices: d.edgeLinkIndices,
|
|
2971
3217
|
positions: d.positions
|
|
2972
3218
|
};
|
|
3219
|
+
},
|
|
3220
|
+
{
|
|
3221
|
+
getClickToFocus: () => clickToFocusRef.current,
|
|
3222
|
+
getIs2D: () => is2DRef.current,
|
|
3223
|
+
getNodeDragEnabled: () => enableNodeDragRef.current
|
|
2973
3224
|
}
|
|
2974
3225
|
);
|
|
2975
3226
|
return () => {
|
|
@@ -3116,17 +3367,26 @@ function NetworkGraph3DInner(props, ref) {
|
|
|
3116
3367
|
if (msg.type === "positions") {
|
|
3117
3368
|
const positions = new Float32Array(msg.positions);
|
|
3118
3369
|
dataRef.current.positions = positions;
|
|
3119
|
-
|
|
3370
|
+
const hn = hiddenNodesRef.current;
|
|
3371
|
+
updateNodePositions(
|
|
3372
|
+
nodesMesh,
|
|
3373
|
+
positions,
|
|
3374
|
+
scales,
|
|
3375
|
+
nc,
|
|
3376
|
+
hn && hn.length === nc ? hn : null
|
|
3377
|
+
);
|
|
3120
3378
|
for (let i = 0; i < nc; i++) {
|
|
3121
3379
|
nodes[i].x = positions[i * 3];
|
|
3122
3380
|
nodes[i].y = positions[i * 3 + 1];
|
|
3123
3381
|
nodes[i].z = positions[i * 3 + 2];
|
|
3124
3382
|
}
|
|
3383
|
+
const he = hiddenEdgesRef.current;
|
|
3125
3384
|
updateEdgePositions(
|
|
3126
3385
|
edgeResult.positionArray,
|
|
3127
3386
|
positions,
|
|
3128
3387
|
edgeNodeIndices,
|
|
3129
|
-
edgeResult.geometry
|
|
3388
|
+
edgeResult.geometry,
|
|
3389
|
+
he && he.length === edgeNodeIndices.length ? he : null
|
|
3130
3390
|
);
|
|
3131
3391
|
const selId = selectedNodeIdRef.current;
|
|
3132
3392
|
if (selId && sceneState.selectionRing.visible) {
|
|
@@ -3146,7 +3406,20 @@ function NetworkGraph3DInner(props, ref) {
|
|
|
3146
3406
|
(_b = onLayoutSettledRef.current) == null ? void 0 : _b.call(onLayoutSettledRef);
|
|
3147
3407
|
}
|
|
3148
3408
|
};
|
|
3149
|
-
const
|
|
3409
|
+
const layoutConfig = layoutRef.current;
|
|
3410
|
+
const layoutParams = resolveLayoutParams(nc, layoutConfig);
|
|
3411
|
+
let groups;
|
|
3412
|
+
if (layoutConfig == null ? void 0 : layoutConfig.clusterBy) {
|
|
3413
|
+
const keyOf = (n) => layoutConfig.clusterBy === "type" ? n.type : n.group;
|
|
3414
|
+
const keyToIdx = /* @__PURE__ */ new Map();
|
|
3415
|
+
groups = nodes.map((n) => {
|
|
3416
|
+
const k = keyOf(n);
|
|
3417
|
+
if (k == null) return -1;
|
|
3418
|
+
const ks = String(k);
|
|
3419
|
+
if (!keyToIdx.has(ks)) keyToIdx.set(ks, keyToIdx.size);
|
|
3420
|
+
return keyToIdx.get(ks);
|
|
3421
|
+
});
|
|
3422
|
+
}
|
|
3150
3423
|
worker.postMessage({
|
|
3151
3424
|
type: "init",
|
|
3152
3425
|
nodes: nodes.map((n) => ({ id: n.id })),
|
|
@@ -3155,7 +3428,8 @@ function NetworkGraph3DInner(props, ref) {
|
|
|
3155
3428
|
target: typeof l.target === "object" ? l.target.id : l.target
|
|
3156
3429
|
})),
|
|
3157
3430
|
params: layoutParams,
|
|
3158
|
-
initialPositions: preservedPositionsRef.current
|
|
3431
|
+
initialPositions: preservedPositionsRef.current,
|
|
3432
|
+
groups
|
|
3159
3433
|
});
|
|
3160
3434
|
return () => {
|
|
3161
3435
|
const d = dataRef.current;
|
|
@@ -3180,7 +3454,56 @@ function NetworkGraph3DInner(props, ref) {
|
|
|
3180
3454
|
disposeObject(edgeResult.mesh);
|
|
3181
3455
|
graphObjRef.current = null;
|
|
3182
3456
|
};
|
|
3183
|
-
}, [mergedData, valRange, nodeValueAccessor,
|
|
3457
|
+
}, [mergedData, valRange, nodeValueAccessor, layoutKey]);
|
|
3458
|
+
useEffect(() => {
|
|
3459
|
+
const d = dataRef.current;
|
|
3460
|
+
const gObj = graphObjRef.current;
|
|
3461
|
+
if (!visibleSet && !linkVisibility) {
|
|
3462
|
+
hiddenNodesRef.current = null;
|
|
3463
|
+
hiddenEdgesRef.current = null;
|
|
3464
|
+
} else {
|
|
3465
|
+
const nc = d.nodes.length;
|
|
3466
|
+
const hn = new Uint8Array(nc);
|
|
3467
|
+
if (visibleSet) {
|
|
3468
|
+
for (let i = 0; i < nc; i++) {
|
|
3469
|
+
if (!visibleSet.has(d.nodes[i].id)) hn[i] = 1;
|
|
3470
|
+
}
|
|
3471
|
+
}
|
|
3472
|
+
const ec = d.edgeNodeIndices.length;
|
|
3473
|
+
const he = new Uint8Array(ec);
|
|
3474
|
+
for (let i = 0; i < ec; i++) {
|
|
3475
|
+
const [si, ti] = d.edgeNodeIndices[i];
|
|
3476
|
+
if (hn[si] || hn[ti]) {
|
|
3477
|
+
he[i] = 1;
|
|
3478
|
+
} else if (linkVisibility) {
|
|
3479
|
+
const link = d.links[d.edgeLinkIndices[i]];
|
|
3480
|
+
if (link && !linkVisibility(link)) he[i] = 1;
|
|
3481
|
+
}
|
|
3482
|
+
}
|
|
3483
|
+
hiddenNodesRef.current = visibleSet ? hn : null;
|
|
3484
|
+
hiddenEdgesRef.current = he;
|
|
3485
|
+
}
|
|
3486
|
+
if (gObj && d.positions && d.scales) {
|
|
3487
|
+
updateNodePositions(
|
|
3488
|
+
gObj.nodesMesh,
|
|
3489
|
+
d.positions,
|
|
3490
|
+
d.scales,
|
|
3491
|
+
d.nodes.length,
|
|
3492
|
+
hiddenNodesRef.current
|
|
3493
|
+
);
|
|
3494
|
+
updateEdgePositions(
|
|
3495
|
+
gObj.edgePositionArray,
|
|
3496
|
+
d.positions,
|
|
3497
|
+
d.edgeNodeIndices,
|
|
3498
|
+
gObj.edgeGeometry,
|
|
3499
|
+
hiddenEdgesRef.current
|
|
3500
|
+
);
|
|
3501
|
+
}
|
|
3502
|
+
}, [visibleSet, linkVisibility, mergedData]);
|
|
3503
|
+
useEffect(() => {
|
|
3504
|
+
const s = sceneRef.current;
|
|
3505
|
+
if (s) applyCameraMode2D(s, is2D);
|
|
3506
|
+
}, [is2D]);
|
|
3184
3507
|
useEffect(() => {
|
|
3185
3508
|
const gObj = graphObjRef.current;
|
|
3186
3509
|
const sceneState = sceneRef.current;
|
|
@@ -3248,7 +3571,7 @@ function NetworkGraph3DInner(props, ref) {
|
|
|
3248
3571
|
resolvedStyle.nodeMaxSize
|
|
3249
3572
|
);
|
|
3250
3573
|
dataRef.current.scales = newScales;
|
|
3251
|
-
updateNodePositions(gObj.nodesMesh, positions, newScales, nc);
|
|
3574
|
+
updateNodePositions(gObj.nodesMesh, positions, newScales, nc, hiddenNodesRef.current);
|
|
3252
3575
|
}, [resolvedStyle.nodeMinSize, resolvedStyle.nodeMaxSize, valRange]);
|
|
3253
3576
|
useEffect(() => {
|
|
3254
3577
|
const gObj = graphObjRef.current;
|
|
@@ -3337,6 +3660,17 @@ function NetworkGraph3DInner(props, ref) {
|
|
|
3337
3660
|
const nx = d.positions[idx * 3];
|
|
3338
3661
|
const ny = d.positions[idx * 3 + 1];
|
|
3339
3662
|
const nz = d.positions[idx * 3 + 2];
|
|
3663
|
+
if (is2DRef.current) {
|
|
3664
|
+
const z2 = Math.max(120, Math.min(Math.abs(s.camera.position.z), 500));
|
|
3665
|
+
animateCamera(
|
|
3666
|
+
s.camera,
|
|
3667
|
+
s.controls,
|
|
3668
|
+
{ x: nx, y: ny, z: z2 },
|
|
3669
|
+
{ x: nx, y: ny, z: 0 },
|
|
3670
|
+
duration
|
|
3671
|
+
);
|
|
3672
|
+
return;
|
|
3673
|
+
}
|
|
3340
3674
|
const dist = Math.hypot(nx, ny, nz);
|
|
3341
3675
|
if (dist < 1) return;
|
|
3342
3676
|
const ratio = 1 + 120 / dist;
|
|
@@ -3348,6 +3682,34 @@ function NetworkGraph3DInner(props, ref) {
|
|
|
3348
3682
|
duration
|
|
3349
3683
|
);
|
|
3350
3684
|
},
|
|
3685
|
+
panTo(x2, y2, duration = 600) {
|
|
3686
|
+
const s = sceneRef.current;
|
|
3687
|
+
if (!s) return;
|
|
3688
|
+
const t = s.controls.target;
|
|
3689
|
+
if (is2DRef.current) {
|
|
3690
|
+
animateCamera(
|
|
3691
|
+
s.camera,
|
|
3692
|
+
s.controls,
|
|
3693
|
+
{ x: x2, y: y2, z: s.camera.position.z },
|
|
3694
|
+
{ x: x2, y: y2, z: 0 },
|
|
3695
|
+
duration
|
|
3696
|
+
);
|
|
3697
|
+
} else {
|
|
3698
|
+
const dx = x2 - t.x;
|
|
3699
|
+
const dy = y2 - t.y;
|
|
3700
|
+
animateCamera(
|
|
3701
|
+
s.camera,
|
|
3702
|
+
s.controls,
|
|
3703
|
+
{
|
|
3704
|
+
x: s.camera.position.x + dx,
|
|
3705
|
+
y: s.camera.position.y + dy,
|
|
3706
|
+
z: s.camera.position.z
|
|
3707
|
+
},
|
|
3708
|
+
{ x: x2, y: y2, z: t.z },
|
|
3709
|
+
duration
|
|
3710
|
+
);
|
|
3711
|
+
}
|
|
3712
|
+
},
|
|
3351
3713
|
appendData(newNodes, newLinks) {
|
|
3352
3714
|
if (newNodes.length === 0 && newLinks.length === 0) return 0;
|
|
3353
3715
|
const existingIds = new Set(dataRef.current.nodes.map((n) => n.id));
|
|
@@ -3376,6 +3738,32 @@ function NetworkGraph3DInner(props, ref) {
|
|
|
3376
3738
|
s.renderer.render(s.scene, s.camera);
|
|
3377
3739
|
return s.renderer.domElement.toDataURL("image/png");
|
|
3378
3740
|
},
|
|
3741
|
+
getGraphSnapshot() {
|
|
3742
|
+
var _a;
|
|
3743
|
+
const gObj = graphObjRef.current;
|
|
3744
|
+
const d = dataRef.current;
|
|
3745
|
+
if (!gObj || !d.positions) return null;
|
|
3746
|
+
return {
|
|
3747
|
+
positions: d.positions,
|
|
3748
|
+
count: d.nodes.length,
|
|
3749
|
+
colors: ((_a = gObj.nodesMesh.instanceColor) == null ? void 0 : _a.array) ?? null,
|
|
3750
|
+
hidden: hiddenNodesRef.current,
|
|
3751
|
+
selectedIndex: selectedNodeIdRef.current ? d.nodeIdToIndex.get(selectedNodeIdRef.current) ?? -1 : -1
|
|
3752
|
+
};
|
|
3753
|
+
},
|
|
3754
|
+
getViewportRect() {
|
|
3755
|
+
const s = sceneRef.current;
|
|
3756
|
+
if (!s) return null;
|
|
3757
|
+
const cam = s.camera;
|
|
3758
|
+
const dist = Math.abs(cam.position.z);
|
|
3759
|
+
const halfH = Math.tan(cam.fov * Math.PI / 360) * dist;
|
|
3760
|
+
return {
|
|
3761
|
+
cx: cam.position.x,
|
|
3762
|
+
cy: cam.position.y,
|
|
3763
|
+
halfW: halfH * cam.aspect,
|
|
3764
|
+
halfH
|
|
3765
|
+
};
|
|
3766
|
+
},
|
|
3379
3767
|
reheatLayout() {
|
|
3380
3768
|
const gObj = graphObjRef.current;
|
|
3381
3769
|
if (gObj == null ? void 0 : gObj.worker) {
|
|
@@ -3397,6 +3785,150 @@ function NetworkGraph3DInner(props, ref) {
|
|
|
3397
3785
|
);
|
|
3398
3786
|
}
|
|
3399
3787
|
const NetworkGraph3D = forwardRef(NetworkGraph3DInner);
|
|
3788
|
+
function GraphMinimap({
|
|
3789
|
+
graphRef,
|
|
3790
|
+
width = 200,
|
|
3791
|
+
height = 140,
|
|
3792
|
+
backgroundColor,
|
|
3793
|
+
viewportColor = "#94a3b8",
|
|
3794
|
+
dotRadius = 1.5,
|
|
3795
|
+
fps = 15,
|
|
3796
|
+
padding = 0.08,
|
|
3797
|
+
className,
|
|
3798
|
+
style
|
|
3799
|
+
}) {
|
|
3800
|
+
const canvasRef = useRef(null);
|
|
3801
|
+
const fitRef = useRef(null);
|
|
3802
|
+
const draggingRef = useRef(false);
|
|
3803
|
+
useEffect(() => {
|
|
3804
|
+
const canvas = canvasRef.current;
|
|
3805
|
+
if (!canvas) return;
|
|
3806
|
+
const ctx = canvas.getContext("2d");
|
|
3807
|
+
if (!ctx) return;
|
|
3808
|
+
const dpr = Math.min(window.devicePixelRatio || 1, 2);
|
|
3809
|
+
canvas.width = width * dpr;
|
|
3810
|
+
canvas.height = height * dpr;
|
|
3811
|
+
let raf = 0;
|
|
3812
|
+
let last = 0;
|
|
3813
|
+
const interval2 = 1e3 / fps;
|
|
3814
|
+
const draw = (now2) => {
|
|
3815
|
+
var _a, _b;
|
|
3816
|
+
raf = requestAnimationFrame(draw);
|
|
3817
|
+
if (now2 - last < interval2) return;
|
|
3818
|
+
last = now2;
|
|
3819
|
+
ctx.setTransform(dpr, 0, 0, dpr, 0, 0);
|
|
3820
|
+
ctx.clearRect(0, 0, width, height);
|
|
3821
|
+
if (backgroundColor) {
|
|
3822
|
+
ctx.fillStyle = backgroundColor;
|
|
3823
|
+
ctx.fillRect(0, 0, width, height);
|
|
3824
|
+
}
|
|
3825
|
+
const snap = (_a = graphRef.current) == null ? void 0 : _a.getGraphSnapshot();
|
|
3826
|
+
if (!snap || snap.count === 0) {
|
|
3827
|
+
fitRef.current = null;
|
|
3828
|
+
return;
|
|
3829
|
+
}
|
|
3830
|
+
const { positions, count, colors, hidden, selectedIndex } = snap;
|
|
3831
|
+
let minX = Infinity, maxX = -Infinity, minY = Infinity, maxY = -Infinity;
|
|
3832
|
+
for (let i = 0; i < count; i++) {
|
|
3833
|
+
if (hidden && hidden[i]) continue;
|
|
3834
|
+
const x2 = positions[i * 3];
|
|
3835
|
+
const y2 = positions[i * 3 + 1];
|
|
3836
|
+
if (x2 < minX) minX = x2;
|
|
3837
|
+
if (x2 > maxX) maxX = x2;
|
|
3838
|
+
if (y2 < minY) minY = y2;
|
|
3839
|
+
if (y2 > maxY) maxY = y2;
|
|
3840
|
+
}
|
|
3841
|
+
if (!isFinite(minX)) {
|
|
3842
|
+
fitRef.current = null;
|
|
3843
|
+
return;
|
|
3844
|
+
}
|
|
3845
|
+
const spanX = Math.max(maxX - minX, 1);
|
|
3846
|
+
const spanY = Math.max(maxY - minY, 1);
|
|
3847
|
+
const pad = Math.min(width, height) * padding;
|
|
3848
|
+
const scale = Math.min(
|
|
3849
|
+
(width - pad * 2) / spanX,
|
|
3850
|
+
(height - pad * 2) / spanY
|
|
3851
|
+
);
|
|
3852
|
+
const offsetX = width / 2 - (minX + maxX) / 2 * scale;
|
|
3853
|
+
const offsetY = height / 2 + (minY + maxY) / 2 * scale;
|
|
3854
|
+
fitRef.current = { scale, offsetX, offsetY };
|
|
3855
|
+
const r = dotRadius;
|
|
3856
|
+
for (let i = 0; i < count; i++) {
|
|
3857
|
+
if (hidden && hidden[i]) continue;
|
|
3858
|
+
const cx = positions[i * 3] * scale + offsetX;
|
|
3859
|
+
const cy = -positions[i * 3 + 1] * scale + offsetY;
|
|
3860
|
+
if (colors) {
|
|
3861
|
+
const cr = Math.min(255, Math.round(colors[i * 3] * 255));
|
|
3862
|
+
const cg = Math.min(255, Math.round(colors[i * 3 + 1] * 255));
|
|
3863
|
+
const cb = Math.min(255, Math.round(colors[i * 3 + 2] * 255));
|
|
3864
|
+
ctx.fillStyle = `rgb(${cr},${cg},${cb})`;
|
|
3865
|
+
} else {
|
|
3866
|
+
ctx.fillStyle = viewportColor;
|
|
3867
|
+
}
|
|
3868
|
+
const rad = i === selectedIndex ? r * 2 : r;
|
|
3869
|
+
ctx.beginPath();
|
|
3870
|
+
ctx.arc(cx, cy, rad, 0, Math.PI * 2);
|
|
3871
|
+
ctx.fill();
|
|
3872
|
+
}
|
|
3873
|
+
const vp = (_b = graphRef.current) == null ? void 0 : _b.getViewportRect();
|
|
3874
|
+
if (vp) {
|
|
3875
|
+
const x2 = (vp.cx - vp.halfW) * scale + offsetX;
|
|
3876
|
+
const y2 = -(vp.cy + vp.halfH) * scale + offsetY;
|
|
3877
|
+
const w = vp.halfW * 2 * scale;
|
|
3878
|
+
const h = vp.halfH * 2 * scale;
|
|
3879
|
+
ctx.strokeStyle = viewportColor;
|
|
3880
|
+
ctx.lineWidth = 1;
|
|
3881
|
+
ctx.strokeRect(x2, y2, w, h);
|
|
3882
|
+
ctx.fillStyle = viewportColor + "1a";
|
|
3883
|
+
ctx.fillRect(x2, y2, w, h);
|
|
3884
|
+
}
|
|
3885
|
+
};
|
|
3886
|
+
raf = requestAnimationFrame(draw);
|
|
3887
|
+
return () => cancelAnimationFrame(raf);
|
|
3888
|
+
}, [graphRef, width, height, backgroundColor, viewportColor, dotRadius, fps, padding]);
|
|
3889
|
+
const panToPointer = (e) => {
|
|
3890
|
+
var _a;
|
|
3891
|
+
const fit = fitRef.current;
|
|
3892
|
+
const canvas = canvasRef.current;
|
|
3893
|
+
if (!fit || !canvas) return;
|
|
3894
|
+
const rect = canvas.getBoundingClientRect();
|
|
3895
|
+
const px = e.clientX - rect.left;
|
|
3896
|
+
const py = e.clientY - rect.top;
|
|
3897
|
+
const wx = (px - fit.offsetX) / fit.scale;
|
|
3898
|
+
const wy = -(py - fit.offsetY) / fit.scale;
|
|
3899
|
+
(_a = graphRef.current) == null ? void 0 : _a.panTo(wx, wy, draggingRef.current ? 0 : 300);
|
|
3900
|
+
};
|
|
3901
|
+
return /* @__PURE__ */ jsx(
|
|
3902
|
+
"canvas",
|
|
3903
|
+
{
|
|
3904
|
+
ref: canvasRef,
|
|
3905
|
+
className,
|
|
3906
|
+
style: {
|
|
3907
|
+
width,
|
|
3908
|
+
height,
|
|
3909
|
+
cursor: "pointer",
|
|
3910
|
+
touchAction: "none",
|
|
3911
|
+
display: "block",
|
|
3912
|
+
...style
|
|
3913
|
+
},
|
|
3914
|
+
onPointerDown: (e) => {
|
|
3915
|
+
draggingRef.current = true;
|
|
3916
|
+
e.currentTarget.setPointerCapture(e.pointerId);
|
|
3917
|
+
panToPointer(e);
|
|
3918
|
+
},
|
|
3919
|
+
onPointerMove: (e) => {
|
|
3920
|
+
if (draggingRef.current) panToPointer(e);
|
|
3921
|
+
},
|
|
3922
|
+
onPointerUp: (e) => {
|
|
3923
|
+
draggingRef.current = false;
|
|
3924
|
+
e.currentTarget.releasePointerCapture(e.pointerId);
|
|
3925
|
+
},
|
|
3926
|
+
onPointerCancel: () => {
|
|
3927
|
+
draggingRef.current = false;
|
|
3928
|
+
}
|
|
3929
|
+
}
|
|
3930
|
+
);
|
|
3931
|
+
}
|
|
3400
3932
|
function forceCenter(x2, y2, z2) {
|
|
3401
3933
|
var nodes, strength = 1;
|
|
3402
3934
|
if (x2 == null) x2 = 0;
|
|
@@ -5465,6 +5997,7 @@ function CtrlBtn({ children, title, onClick }) {
|
|
|
5465
5997
|
export {
|
|
5466
5998
|
DEFAULT_LAYOUT,
|
|
5467
5999
|
DEFAULT_STYLE,
|
|
6000
|
+
GraphMinimap,
|
|
5468
6001
|
NetworkGraph3D,
|
|
5469
6002
|
NodeDetailPanel,
|
|
5470
6003
|
SubgraphView2D,
|
|
@@ -5475,6 +6008,7 @@ export {
|
|
|
5475
6008
|
computeHighlightSet,
|
|
5476
6009
|
minimal,
|
|
5477
6010
|
neon,
|
|
6011
|
+
paper,
|
|
5478
6012
|
resolveTheme,
|
|
5479
6013
|
zoomToFitPositions
|
|
5480
6014
|
};
|