@fnndsc/orrery 0.1.0

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (116) hide show
  1. package/README.md +12 -0
  2. package/dist/controls/cameraRig.d.ts +223 -0
  3. package/dist/controls/cameraRig.js +353 -0
  4. package/dist/controls/cameraRig.js.map +1 -0
  5. package/dist/controls/gestures.d.ts +133 -0
  6. package/dist/controls/gestures.js +282 -0
  7. package/dist/controls/gestures.js.map +1 -0
  8. package/dist/controls/index.d.ts +9 -0
  9. package/dist/controls/index.js +10 -0
  10. package/dist/controls/index.js.map +1 -0
  11. package/dist/controls/picker.d.ts +117 -0
  12. package/dist/controls/picker.js +167 -0
  13. package/dist/controls/picker.js.map +1 -0
  14. package/dist/controls/replay.d.ts +94 -0
  15. package/dist/controls/replay.js +147 -0
  16. package/dist/controls/replay.js.map +1 -0
  17. package/dist/draw/censusField.d.ts +113 -0
  18. package/dist/draw/censusField.js +241 -0
  19. package/dist/draw/censusField.js.map +1 -0
  20. package/dist/draw/constants.d.ts +13 -0
  21. package/dist/draw/constants.js +14 -0
  22. package/dist/draw/constants.js.map +1 -0
  23. package/dist/draw/geometry.d.ts +33 -0
  24. package/dist/draw/geometry.js +55 -0
  25. package/dist/draw/geometry.js.map +1 -0
  26. package/dist/draw/handoff.d.ts +11 -0
  27. package/dist/draw/handoff.js +12 -0
  28. package/dist/draw/handoff.js.map +1 -0
  29. package/dist/draw/handoffField.d.ts +74 -0
  30. package/dist/draw/handoffField.js +151 -0
  31. package/dist/draw/handoffField.js.map +1 -0
  32. package/dist/draw/index.d.ts +20 -0
  33. package/dist/draw/index.js +21 -0
  34. package/dist/draw/index.js.map +1 -0
  35. package/dist/draw/labelField.d.ts +63 -0
  36. package/dist/draw/labelField.js +149 -0
  37. package/dist/draw/labelField.js.map +1 -0
  38. package/dist/draw/lamps.d.ts +16 -0
  39. package/dist/draw/lamps.js +17 -0
  40. package/dist/draw/lamps.js.map +1 -0
  41. package/dist/draw/nebula.d.ts +8 -0
  42. package/dist/draw/nebula.js +28 -0
  43. package/dist/draw/nebula.js.map +1 -0
  44. package/dist/draw/palette.d.ts +41 -0
  45. package/dist/draw/palette.js +32 -0
  46. package/dist/draw/palette.js.map +1 -0
  47. package/dist/draw/sphereField.d.ts +98 -0
  48. package/dist/draw/sphereField.js +168 -0
  49. package/dist/draw/sphereField.js.map +1 -0
  50. package/dist/draw/starField.d.ts +127 -0
  51. package/dist/draw/starField.js +267 -0
  52. package/dist/draw/starField.js.map +1 -0
  53. package/dist/draw/stars.d.ts +65 -0
  54. package/dist/draw/stars.js +132 -0
  55. package/dist/draw/stars.js.map +1 -0
  56. package/dist/draw/timing.d.ts +11 -0
  57. package/dist/draw/timing.js +12 -0
  58. package/dist/draw/timing.js.map +1 -0
  59. package/dist/draw/tubeField.d.ts +131 -0
  60. package/dist/draw/tubeField.js +352 -0
  61. package/dist/draw/tubeField.js.map +1 -0
  62. package/dist/draw/tubes.d.ts +41 -0
  63. package/dist/draw/tubes.js +116 -0
  64. package/dist/draw/tubes.js.map +1 -0
  65. package/dist/index.d.ts +15 -0
  66. package/dist/index.js +15 -0
  67. package/dist/index.js.map +1 -0
  68. package/dist/layout/accretion.d.ts +31 -0
  69. package/dist/layout/accretion.js +384 -0
  70. package/dist/layout/accretion.js.map +1 -0
  71. package/dist/layout/constellations.d.ts +25 -0
  72. package/dist/layout/constellations.js +197 -0
  73. package/dist/layout/constellations.js.map +1 -0
  74. package/dist/layout/galaxy.d.ts +12 -0
  75. package/dist/layout/galaxy.js +99 -0
  76. package/dist/layout/galaxy.js.map +1 -0
  77. package/dist/layout/hierarchy.d.ts +45 -0
  78. package/dist/layout/hierarchy.js +464 -0
  79. package/dist/layout/hierarchy.js.map +1 -0
  80. package/dist/layout/index.d.ts +20 -0
  81. package/dist/layout/index.js +21 -0
  82. package/dist/layout/index.js.map +1 -0
  83. package/dist/layout/layoutInput.d.ts +29 -0
  84. package/dist/layout/layoutInput.js +45 -0
  85. package/dist/layout/layoutInput.js.map +1 -0
  86. package/dist/layout/molecule.d.ts +64 -0
  87. package/dist/layout/molecule.js +155 -0
  88. package/dist/layout/molecule.js.map +1 -0
  89. package/dist/layout/pull.d.ts +94 -0
  90. package/dist/layout/pull.js +137 -0
  91. package/dist/layout/pull.js.map +1 -0
  92. package/dist/layout/ranked.d.ts +75 -0
  93. package/dist/layout/ranked.js +148 -0
  94. package/dist/layout/ranked.js.map +1 -0
  95. package/dist/layout/registry.d.ts +23 -0
  96. package/dist/layout/registry.js +165 -0
  97. package/dist/layout/registry.js.map +1 -0
  98. package/dist/layout/seeded.d.ts +32 -0
  99. package/dist/layout/seeded.js +48 -0
  100. package/dist/layout/seeded.js.map +1 -0
  101. package/dist/layout/types.d.ts +81 -0
  102. package/dist/layout/types.js +14 -0
  103. package/dist/layout/types.js.map +1 -0
  104. package/dist/scene/index.d.ts +6 -0
  105. package/dist/scene/index.js +7 -0
  106. package/dist/scene/index.js.map +1 -0
  107. package/dist/scene/orrery.d.ts +592 -0
  108. package/dist/scene/orrery.js +1555 -0
  109. package/dist/scene/orrery.js.map +1 -0
  110. package/dist/types/encoding.d.ts +43 -0
  111. package/dist/types/encoding.js +7 -0
  112. package/dist/types/encoding.js.map +1 -0
  113. package/dist/types/space.d.ts +12 -0
  114. package/dist/types/space.js +10 -0
  115. package/dist/types/space.js.map +1 -0
  116. package/package.json +57 -0
@@ -0,0 +1 @@
1
+ {"version":3,"file":"tubeField.js","sourceRoot":"","sources":["../../src/draw/tubeField.ts"],"names":[],"mappings":"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"}
@@ -0,0 +1,41 @@
1
+ /**
2
+ * @file Tubes: the lit cylinders a solid edge wears, carrying a pulse from parent to child — streaming into a live stage, replaying a finished run.
3
+ *
4
+ * @module
5
+ */
6
+ import * as THREE from 'three';
7
+ /**
8
+ * The most job-to-job edges a census draws as tubes. Past it the census
9
+ * keeps its lines: a lab's whole history is hundreds of thousands of
10
+ * edges, and that many cylinders would stall the tablet it is read on.
11
+ */
12
+ export declare const CENSUS_TUBE_CAP: number;
13
+ export declare const TUBE_VERTEX: string;
14
+ /**
15
+ * A tube lit by its facing, carrying a pulse from parent (its foot) to
16
+ * child (its head): mode 1 streams (live), mode 2 replays the run — each
17
+ * stage at vStart into a cycle that rests and repeats — mode 0 rests.
18
+ */
19
+ export declare const TUBE_FRAGMENT: string;
20
+ /** A unit tube, one high along y, centred: its foot at -0.5, its head at +0.5. */
21
+ export declare function tubeGeometry_get(): THREE.CylinderGeometry;
22
+ /** One tube: where it runs, how wide, its hue, and its pulse. */
23
+ export interface TubeSpec {
24
+ from: THREE.Vector3;
25
+ to: THREE.Vector3;
26
+ width: number;
27
+ color: THREE.Color;
28
+ /** 0 rests, 1 streams (a live stage), 2 replays (a finished run). */
29
+ mode: number;
30
+ /** When, into the replay's cycle, the wave sets off along it. */
31
+ start: number;
32
+ }
33
+ /**
34
+ * Makes one instanced mesh of tubes from their specs: the shared unit tube
35
+ * stretched and turned per spec, each carrying its own hue and pulse.
36
+ *
37
+ * @param specs - The tubes.
38
+ * @param cycle - The replay's period, in ms.
39
+ * @returns The mesh, not yet added to anything.
40
+ */
41
+ export declare function tubeMesh_make(specs: ReadonlyArray<TubeSpec>, cycle: number): THREE.InstancedMesh;
@@ -0,0 +1,116 @@
1
+ /**
2
+ * @file Tubes: the lit cylinders a solid edge wears, carrying a pulse from parent to child — streaming into a live stage, replaying a finished run.
3
+ *
4
+ * @module
5
+ */
6
+ import * as THREE from 'three';
7
+ import { PULSE_TRIP_MS } from './timing.js';
8
+ /**
9
+ * The most job-to-job edges a census draws as tubes. Past it the census
10
+ * keeps its lines: a lab's whole history is hundreds of thousands of
11
+ * edges, and that many cylinders would stall the tablet it is read on.
12
+ */
13
+ export const CENSUS_TUBE_CAP = 20_000;
14
+ export const TUBE_VERTEX = `
15
+ attribute vec3 aColor;
16
+ attribute float aMode;
17
+ attribute float aStart;
18
+ varying vec3 vColor;
19
+ varying float vMode;
20
+ varying float vStart;
21
+ varying float vAlong;
22
+ varying vec3 vNormal;
23
+ varying vec3 vView;
24
+ void main() {
25
+ vAlong = position.y + 0.5;
26
+ vec4 mv = modelViewMatrix * instanceMatrix * vec4(position, 1.0);
27
+ vView = -mv.xyz;
28
+ vNormal = normalize(normalMatrix * mat3(instanceMatrix) * normal);
29
+ vColor = aColor;
30
+ vMode = aMode;
31
+ vStart = aStart;
32
+ gl_Position = projectionMatrix * mv;
33
+ }`;
34
+ /**
35
+ * A tube lit by its facing, carrying a pulse from parent (its foot) to
36
+ * child (its head): mode 1 streams (live), mode 2 replays the run — each
37
+ * stage at vStart into a cycle that rests and repeats — mode 0 rests.
38
+ */
39
+ export const TUBE_FRAGMENT = `
40
+ uniform float time;
41
+ uniform float opacity;
42
+ uniform float born;
43
+ uniform float cycle;
44
+ varying vec3 vColor;
45
+ varying float vMode;
46
+ varying float vStart;
47
+ varying float vAlong;
48
+ varying vec3 vNormal;
49
+ varying vec3 vView;
50
+ void main() {
51
+ float facing = abs(dot(normalize(vNormal), normalize(vView)));
52
+ vec3 base = vColor * (0.35 + 0.65 * facing);
53
+ float pulse = 0.0;
54
+ if (vMode > 0.5 && vMode < 1.5) {
55
+ float head = fract(time / ${PULSE_TRIP_MS.toFixed(1)});
56
+ pulse = smoothstep(0.14, 0.0, abs(vAlong - head));
57
+ } else if (vMode > 1.5) {
58
+ // A finished feed replays its run: the wave goes stage by stage in the
59
+ // order the stages ran, rests, and goes again.
60
+ float local = mod(time - born, cycle) - vStart;
61
+ float head = local / ${(PULSE_TRIP_MS / 2).toFixed(1)};
62
+ if (head > -0.1 && head < 1.2) pulse = smoothstep(0.14, 0.0, abs(vAlong - head));
63
+ }
64
+ gl_FragColor = vec4(base + vec3(1.0, 0.95, 0.8) * pulse * 1.3, opacity);
65
+ }`;
66
+ /** The tube every solid edge wears, stretched and turned per edge. */
67
+ let tubeGeometry = null;
68
+ /** A unit tube, one high along y, centred: its foot at -0.5, its head at +0.5. */
69
+ export function tubeGeometry_get() {
70
+ if (tubeGeometry === null)
71
+ tubeGeometry = new THREE.CylinderGeometry(1, 1, 1, 10, 1, true);
72
+ return tubeGeometry;
73
+ }
74
+ /**
75
+ * Makes one instanced mesh of tubes from their specs: the shared unit tube
76
+ * stretched and turned per spec, each carrying its own hue and pulse.
77
+ *
78
+ * @param specs - The tubes.
79
+ * @param cycle - The replay's period, in ms.
80
+ * @returns The mesh, not yet added to anything.
81
+ */
82
+ export function tubeMesh_make(specs, cycle) {
83
+ const now = performance.now();
84
+ const material = new THREE.ShaderMaterial({
85
+ uniforms: { time: { value: now }, opacity: { value: 1 }, born: { value: now }, cycle: { value: cycle } },
86
+ vertexShader: TUBE_VERTEX,
87
+ fragmentShader: TUBE_FRAGMENT,
88
+ transparent: true,
89
+ });
90
+ const geometry = tubeGeometry_get().clone();
91
+ const colors = new Float32Array(specs.length * 3);
92
+ const modes = new Float32Array(specs.length);
93
+ const starts = new Float32Array(specs.length);
94
+ const mesh = new THREE.InstancedMesh(geometry, material, specs.length);
95
+ const up = new THREE.Vector3(0, 1, 0);
96
+ const carrier = new THREE.Object3D();
97
+ specs.forEach((spec, i) => {
98
+ const along = spec.to.clone().sub(spec.from);
99
+ const length = along.length();
100
+ carrier.position.copy(spec.from).addScaledVector(along, 0.5);
101
+ carrier.quaternion.setFromUnitVectors(up, length > 0 ? along.divideScalar(length) : up);
102
+ carrier.scale.set(spec.width, length, spec.width);
103
+ carrier.updateMatrix();
104
+ mesh.setMatrixAt(i, carrier.matrix);
105
+ colors.set([spec.color.r, spec.color.g, spec.color.b], i * 3);
106
+ modes[i] = spec.mode;
107
+ starts[i] = spec.start;
108
+ });
109
+ geometry.setAttribute('aColor', new THREE.InstancedBufferAttribute(colors, 3));
110
+ geometry.setAttribute('aMode', new THREE.InstancedBufferAttribute(modes, 1));
111
+ geometry.setAttribute('aStart', new THREE.InstancedBufferAttribute(starts, 1));
112
+ mesh.instanceMatrix.needsUpdate = true;
113
+ mesh.frustumCulled = false;
114
+ return mesh;
115
+ }
116
+ //# sourceMappingURL=tubes.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"tubes.js","sourceRoot":"","sources":["../../src/draw/tubes.ts"],"names":[],"mappings":"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"}
@@ -0,0 +1,15 @@
1
+ /**
2
+ * @file orrery: the model of the heavens a surface draws.
3
+ *
4
+ * Three layers, each kept to itself: `layout/` computes where things stand
5
+ * (pure, no renderer), `draw/` shows them, `controls/` steers the view. A
6
+ * surface hands in a graph and an encoding and knows nothing of the rest;
7
+ * orrery knows nothing of what the graph's nodes stand for.
8
+ *
9
+ * @module
10
+ */
11
+ export * from './layout/index.js';
12
+ export type { NodeState, NodeLook, Paint, PaletteToken } from './types/encoding.js';
13
+ export * from './draw/index.js';
14
+ export * from './controls/index.js';
15
+ export * from './scene/index.js';
package/dist/index.js ADDED
@@ -0,0 +1,15 @@
1
+ /**
2
+ * @file orrery: the model of the heavens a surface draws.
3
+ *
4
+ * Three layers, each kept to itself: `layout/` computes where things stand
5
+ * (pure, no renderer), `draw/` shows them, `controls/` steers the view. A
6
+ * surface hands in a graph and an encoding and knows nothing of the rest;
7
+ * orrery knows nothing of what the graph's nodes stand for.
8
+ *
9
+ * @module
10
+ */
11
+ export * from './layout/index.js';
12
+ export * from './draw/index.js';
13
+ export * from './controls/index.js';
14
+ export * from './scene/index.js';
15
+ //# sourceMappingURL=index.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"index.js","sourceRoot":"","sources":["../src/index.ts"],"names":[],"mappings":"AAAA;;;;;;;;;GASG;AACH,cAAc,mBAAmB,CAAC;AAElC,cAAc,iBAAiB,CAAC;AAChC,cAAc,qBAAqB,CAAC;AACpC,cAAc,kBAAkB,CAAC"}
@@ -0,0 +1,31 @@
1
+ import { type LayoutNode, type PhysicsTerms, type Positions } from './types.js';
2
+ /** Steps a walker takes before it sticks to its closest kin regardless. */
3
+ export declare const STEP_BUDGET: number;
4
+ /**
5
+ * How alike two feeds are by what they ran: the weight of the plugins both
6
+ * ran over the weight of the plugins either ran.
7
+ *
8
+ * @param a - One feed's plugins.
9
+ * @param b - The other's.
10
+ * @param weights - How much each plugin says.
11
+ * @returns 0..1.
12
+ */
13
+ export declare function feedLikeness_of(a: ReadonlySet<string>, b: ReadonlySet<string>, weights: ReadonlyMap<string, number>): number;
14
+ /**
15
+ * Grows a space by accretion.
16
+ *
17
+ * Nodes of one `group` are one feed; a feed's time is the least
18
+ * `attrs.createdAt` among its nodes (feeds without one come after, by key),
19
+ * and its plugins are its nodes' `attrs.plugin`. A node with no group (an
20
+ * anchor) stands at the centre. When every node is held at its seed, the
21
+ * seeds are the answer.
22
+ *
23
+ * @param nodes - Every node.
24
+ * @param _physics - The terms of the settle; a coral has none (nothing settles once stuck).
25
+ * @param onProgress - Told how far it has come, 0..1.
26
+ * @returns Every node's position, and each node's arrival (its feed's place in the order).
27
+ */
28
+ export declare function accretion_layout(nodes: ReadonlyArray<LayoutNode>, _physics: PhysicsTerms, onProgress?: (fraction: number) => void): {
29
+ positions: Positions;
30
+ arrival: Record<string, number>;
31
+ };
@@ -0,0 +1,384 @@
1
+ /**
2
+ * @file Accretion: a space grown in the order it was made.
3
+ *
4
+ * Feeds arrive one at a time, oldest first. The first stands at the centre;
5
+ * each after it is launched from a sphere round what has grown so far and
6
+ * wanders — a random walk with a gentle drift toward the feed most like it
7
+ * — until it touches a feed already placed. It sticks there with a chance
8
+ * equal to how alike the two are, else it steps away and wanders on; a
9
+ * feed that runs out of steps sticks to its closest kin, starting a branch.
10
+ * So the space grows as a coral: like feeds on like, a stranger on a limb
11
+ * of its own, the oldest work at the heart.
12
+ *
13
+ * Likeness is what the feeds ran, weighted as constellations weigh it: a
14
+ * plugin in every feed says nothing, a rare one says much. The walk is
15
+ * seeded from each feed's own key, so the same lab grows the same coral.
16
+ * A feed is one particle — a ball the size of its molecule — and its
17
+ * molecule unfolds in place once it has stuck; nothing already placed
18
+ * moves.
19
+ *
20
+ * Pure: nodes in, positions and arrival order out, run in the worker.
21
+ *
22
+ * @module
23
+ */
24
+ import { pluginWeights_of } from './constellations.js';
25
+ import { randomFor_key } from './seeded.js';
26
+ import { NODE_RADIUS } from './types.js';
27
+ /** The gap left between two stuck balls. */
28
+ const STICK_GAP = 0.4;
29
+ /** Steps a walker takes before it sticks to its closest kin regardless. */
30
+ export const STEP_BUDGET = 400;
31
+ /**
32
+ * How hard a walker drifts toward its most similar placed feed, against its
33
+ * random step. Tuned on synthetic labs of three pipeline families (eight
34
+ * labs of sixty feeds): 0.2-0.35 grew a feed next to its own family about
35
+ * three times in four, stronger drift less often — a walker pulled straight
36
+ * at its kin meets the strangers in the way.
37
+ */
38
+ const DRIFT = 0.35;
39
+ /**
40
+ * The least chance a touch sticks, so strangers do meet. Kept small: at 0.01
41
+ * a feed grew next to its own family four times in five, at 0.1 two in three.
42
+ * A walker out of steps sticks to its kin anyway.
43
+ */
44
+ const STICK_FLOOR = 0.01;
45
+ /** How far past the grown space a walker is launched, in its own radii. */
46
+ const LAUNCH_MARGIN = 3;
47
+ /**
48
+ * How alike two feeds are by what they ran: the weight of the plugins both
49
+ * ran over the weight of the plugins either ran.
50
+ *
51
+ * @param a - One feed's plugins.
52
+ * @param b - The other's.
53
+ * @param weights - How much each plugin says.
54
+ * @returns 0..1.
55
+ */
56
+ export function feedLikeness_of(a, b, weights) {
57
+ let both = 0;
58
+ let either = 0;
59
+ for (const plugin of new Set([...a, ...b])) {
60
+ const weight = weights.get(plugin) ?? 0;
61
+ either += weight;
62
+ if (a.has(plugin) && b.has(plugin))
63
+ both += weight;
64
+ }
65
+ return either === 0 ? 0 : both / either;
66
+ }
67
+ /** How far a child stands past its parent's and its own radii: the universe's own edge length. */
68
+ const EDGE_GAP = 1.4;
69
+ /** How widely a node's children fan round its own heading, in radians. */
70
+ const FAN = Math.PI / 3;
71
+ /**
72
+ * A feed's molecule unfolded alone, centred, with the ball that holds it: a
73
+ * root at the heart, each child one edge past its parent, fanned round its
74
+ * parent's heading so a chain reaches out and a fan opens. Compact at the
75
+ * universe's own edge lengths — a force settle sized for the DAG pane unfolded
76
+ * a feed of four stages fourteen units wide and the space into spokes.
77
+ */
78
+ function molecule_of(nodes, random) {
79
+ const local = new Map();
80
+ const byId = new Map(nodes.map((node) => [node.id, node]));
81
+ const children = new Map();
82
+ const roots = [];
83
+ for (const node of nodes) {
84
+ const parent = node.parents.find((id) => byId.has(id));
85
+ if (parent === undefined)
86
+ roots.push(node);
87
+ else
88
+ children.set(parent, [...(children.get(parent) ?? []), node]);
89
+ }
90
+ const heading = new Map();
91
+ const queue = [];
92
+ roots.forEach((root, index) => {
93
+ const d = direction_of(random);
94
+ const reach = index === 0 ? 0 : root.radius * 2 + EDGE_GAP;
95
+ local.set(root.id, [d[0] * reach, d[1] * reach, d[2] * reach]);
96
+ heading.set(root.id, d);
97
+ queue.push(root);
98
+ });
99
+ for (let node = queue.shift(); node !== undefined; node = queue.shift()) {
100
+ const at = local.get(node.id);
101
+ const ahead = heading.get(node.id);
102
+ for (const child of children.get(node.id) ?? []) {
103
+ if (local.has(child.id))
104
+ continue;
105
+ // A heading within the fan round the parent's: tilted off it, turned about it.
106
+ const tilt = random() * FAN;
107
+ const side = perpendicular_of(ahead, random);
108
+ const d = normalised([
109
+ ahead[0] * Math.cos(tilt) + side[0] * Math.sin(tilt),
110
+ ahead[1] * Math.cos(tilt) + side[1] * Math.sin(tilt),
111
+ ahead[2] * Math.cos(tilt) + side[2] * Math.sin(tilt),
112
+ ]);
113
+ const length = node.radius + child.radius + EDGE_GAP;
114
+ local.set(child.id, [at[0] + d[0] * length, at[1] + d[1] * length, at[2] + d[2] * length]);
115
+ heading.set(child.id, d);
116
+ queue.push(child);
117
+ }
118
+ }
119
+ // A node the walk never reached (a cycle) stands at the heart.
120
+ for (const node of nodes)
121
+ if (!local.has(node.id))
122
+ local.set(node.id, [0, 0, 0]);
123
+ const centre = [0, 0, 0];
124
+ for (const at of local.values()) {
125
+ centre[0] += at[0] / local.size;
126
+ centre[1] += at[1] / local.size;
127
+ centre[2] += at[2] / local.size;
128
+ }
129
+ let radius = NODE_RADIUS;
130
+ for (const node of nodes) {
131
+ const at = local.get(node.id);
132
+ const moved = [at[0] - centre[0], at[1] - centre[1], at[2] - centre[2]];
133
+ local.set(node.id, moved);
134
+ radius = Math.max(radius, Math.hypot(moved[0], moved[1], moved[2]) + node.radius);
135
+ }
136
+ return { local, radius };
137
+ }
138
+ /** A unit vector along `v`. */
139
+ function normalised(v) {
140
+ const length = Math.max(1e-9, Math.hypot(v[0], v[1], v[2]));
141
+ return [v[0] / length, v[1] / length, v[2] / length];
142
+ }
143
+ /** A unit vector at right angles to `v`, turned at random about it. */
144
+ function perpendicular_of(v, random) {
145
+ const other = Math.abs(v[0]) < 0.9 ? [1, 0, 0] : [0, 1, 0];
146
+ const a = normalised([v[1] * other[2] - v[2] * other[1], v[2] * other[0] - v[0] * other[2], v[0] * other[1] - v[1] * other[0]]);
147
+ const b = [v[1] * a[2] - v[2] * a[1], v[2] * a[0] - v[0] * a[2], v[0] * a[1] - v[1] * a[0]];
148
+ const turn = random() * Math.PI * 2;
149
+ return [a[0] * Math.cos(turn) + b[0] * Math.sin(turn), a[1] * Math.cos(turn) + b[1] * Math.sin(turn), a[2] * Math.cos(turn) + b[2] * Math.sin(turn)];
150
+ }
151
+ /** A point on the unit sphere, from the walker's own chance. */
152
+ function direction_of(random) {
153
+ const z = random() * 2 - 1;
154
+ const angle = random() * Math.PI * 2;
155
+ const ring = Math.sqrt(1 - z * z);
156
+ return [ring * Math.cos(angle), ring * Math.sin(angle), z];
157
+ }
158
+ /** The placed balls, bucketed by place so a walker asks only its neighbours whether it touches. */
159
+ class Grid {
160
+ size;
161
+ cells = new Map();
162
+ constructor(size) {
163
+ this.size = size;
164
+ }
165
+ key(at) {
166
+ return `${Math.floor(at[0] / this.size)},${Math.floor(at[1] / this.size)},${Math.floor(at[2] / this.size)}`;
167
+ }
168
+ add(placed) {
169
+ const key = this.key(placed.centre);
170
+ this.cells.set(key, [...(this.cells.get(key) ?? []), placed]);
171
+ }
172
+ /** Every placed ball a ball of `radius` at `at` touches. */
173
+ touching(at, radius) {
174
+ const out = [];
175
+ const [cx, cy, cz] = [Math.floor(at[0] / this.size), Math.floor(at[1] / this.size), Math.floor(at[2] / this.size)];
176
+ for (let dx = -1; dx <= 1; dx++)
177
+ for (let dy = -1; dy <= 1; dy++)
178
+ for (let dz = -1; dz <= 1; dz++) {
179
+ for (const placed of this.cells.get(`${cx + dx},${cy + dy},${cz + dz}`) ?? []) {
180
+ const reach = radius + placed.particle.radius + STICK_GAP;
181
+ const d = Math.hypot(at[0] - placed.centre[0], at[1] - placed.centre[1], at[2] - placed.centre[2]);
182
+ if (d < reach)
183
+ out.push(placed);
184
+ }
185
+ }
186
+ return out;
187
+ }
188
+ }
189
+ /** Where a ball of `radius` rests touching `other`, on the side `from` lies. */
190
+ function restingAgainst(other, from, radius, random) {
191
+ let away = [from[0] - other.centre[0], from[1] - other.centre[1], from[2] - other.centre[2]];
192
+ const length = Math.hypot(away[0], away[1], away[2]);
193
+ away = length < 1e-9 ? direction_of(random) : [away[0] / length, away[1] / length, away[2] / length];
194
+ const reach = radius + other.particle.radius + STICK_GAP;
195
+ return [other.centre[0] + away[0] * reach, other.centre[1] + away[1] * reach, other.centre[2] + away[2] * reach];
196
+ }
197
+ /**
198
+ * Grows a space by accretion.
199
+ *
200
+ * Nodes of one `group` are one feed; a feed's time is the least
201
+ * `attrs.createdAt` among its nodes (feeds without one come after, by key),
202
+ * and its plugins are its nodes' `attrs.plugin`. A node with no group (an
203
+ * anchor) stands at the centre. When every node is held at its seed, the
204
+ * seeds are the answer.
205
+ *
206
+ * @param nodes - Every node.
207
+ * @param _physics - The terms of the settle; a coral has none (nothing settles once stuck).
208
+ * @param onProgress - Told how far it has come, 0..1.
209
+ * @returns Every node's position, and each node's arrival (its feed's place in the order).
210
+ */
211
+ export function accretion_layout(nodes, _physics, onProgress = () => { }) {
212
+ const positions = {};
213
+ const arrival = {};
214
+ if (nodes.length > 0 && nodes.every((node) => node.frozen === true && node.seed !== undefined)) {
215
+ for (const node of nodes)
216
+ positions[node.id] = node.seed;
217
+ onProgress(1);
218
+ return { positions, arrival };
219
+ }
220
+ const byGroup = new Map();
221
+ for (const node of nodes) {
222
+ if (node.group === null) {
223
+ positions[node.id] = [0, 0, 0];
224
+ continue;
225
+ }
226
+ byGroup.set(node.group, [...(byGroup.get(node.group) ?? []), node]);
227
+ }
228
+ const particles = [...byGroup].map(([key, members]) => {
229
+ const plugins = new Set();
230
+ let created = Number.POSITIVE_INFINITY;
231
+ for (const node of members) {
232
+ const plugin = node.attrs?.['plugin'];
233
+ if (typeof plugin === 'string')
234
+ plugins.add(plugin);
235
+ const at = node.attrs?.['createdAt'];
236
+ if (typeof at === 'number' && at < created)
237
+ created = at;
238
+ }
239
+ if (members.every((node) => node.frozen === true && node.seed !== undefined)) {
240
+ // Already grown: it stays exactly where it stands, a ball round its own centre.
241
+ const seeds = members.map((node) => node.seed);
242
+ const centre = [0, 1, 2].map((axis) => seeds.reduce((sum, at) => sum + at[axis], 0) / seeds.length);
243
+ const local = new Map();
244
+ let radius = NODE_RADIUS;
245
+ for (const node of members) {
246
+ const at = node.seed;
247
+ const moved = [at[0] - centre[0], at[1] - centre[1], at[2] - centre[2]];
248
+ local.set(node.id, moved);
249
+ radius = Math.max(radius, Math.hypot(moved[0], moved[1], moved[2]) + node.radius);
250
+ }
251
+ return { key, nodes: members, plugins, created, local, radius, held: true, centre };
252
+ }
253
+ // Unfolded by its own key, so feeds alike do not stand as clones.
254
+ const { local, radius } = molecule_of(members, randomFor_key(`turn:${key}`));
255
+ return { key, nodes: members, plugins, created, local, radius, held: false };
256
+ });
257
+ // Oldest first; a feed with no time after every timed one, by key.
258
+ particles.sort((a, b) => a.created - b.created || (a.key < b.key ? -1 : a.key > b.key ? 1 : 0));
259
+ const feedsUsing = new Map();
260
+ for (const particle of particles)
261
+ for (const plugin of particle.plugins)
262
+ feedsUsing.set(plugin, (feedsUsing.get(plugin) ?? 0) + 1);
263
+ const weights = pluginWeights_of(feedsUsing, particles.length);
264
+ const biggest = Math.max(NODE_RADIUS, ...particles.map((particle) => particle.radius));
265
+ const grid = new Grid(2 * biggest + STICK_GAP);
266
+ const placed = [];
267
+ let extent = 0;
268
+ const settle = (particle, index, centre) => {
269
+ const holder = { particle, centre };
270
+ placed.push(holder);
271
+ grid.add(holder);
272
+ extent = Math.max(extent, Math.hypot(centre[0], centre[1], centre[2]) + particle.radius);
273
+ for (const node of particle.nodes) {
274
+ const local = particle.local.get(node.id) ?? [0, 0, 0];
275
+ // A held node stands exactly at its seed, to the last bit.
276
+ positions[node.id] = particle.held && node.seed !== undefined ? node.seed : [centre[0] + local[0], centre[1] + local[1], centre[2] + local[2]];
277
+ arrival[node.id] = index;
278
+ }
279
+ };
280
+ // What has grown stays: held feeds stand first, and only newcomers walk.
281
+ particles.forEach((particle, index) => {
282
+ if (particle.held && particle.centre !== undefined)
283
+ settle(particle, index, particle.centre);
284
+ });
285
+ particles.forEach((particle, index) => {
286
+ if (particle.held)
287
+ return;
288
+ const random = randomFor_key(`accrete:${particle.key}`);
289
+ let centre;
290
+ if (placed.length === 0) {
291
+ centre = [0, 0, 0];
292
+ }
293
+ else {
294
+ // Its closest kin: the most alike, the newest among equals.
295
+ let kin = placed[placed.length - 1];
296
+ let kinLikeness = -1;
297
+ for (const other of placed) {
298
+ const likeness = feedLikeness_of(particle.plugins, other.particle.plugins, weights);
299
+ if (likeness >= kinLikeness) {
300
+ kin = other;
301
+ kinLikeness = likeness;
302
+ }
303
+ }
304
+ const launch = extent + LAUNCH_MARGIN * particle.radius + biggest;
305
+ const step = Math.max(0.5, particle.radius * 0.5);
306
+ const start = direction_of(random);
307
+ let at = [start[0] * launch, start[1] * launch, start[2] * launch];
308
+ let stuck = null;
309
+ for (let taken = 0; taken < STEP_BUDGET && stuck === null; taken++) {
310
+ const wander = direction_of(random);
311
+ const toward = [kin.centre[0] - at[0], kin.centre[1] - at[1], kin.centre[2] - at[2]];
312
+ const distance = Math.max(1e-9, Math.hypot(toward[0], toward[1], toward[2]));
313
+ const heading = [
314
+ wander[0] * (1 - DRIFT) + (toward[0] / distance) * DRIFT,
315
+ wander[1] * (1 - DRIFT) + (toward[1] / distance) * DRIFT,
316
+ wander[2] * (1 - DRIFT) + (toward[2] / distance) * DRIFT,
317
+ ];
318
+ const next = [at[0] + heading[0] * step, at[1] + heading[1] * step, at[2] + heading[2] * step];
319
+ const touched = grid.touching(next, particle.radius);
320
+ if (touched.length === 0) {
321
+ // Strayed too far: launched again from the sphere.
322
+ if (Math.hypot(next[0], next[1], next[2]) > launch * 2) {
323
+ const again = direction_of(random);
324
+ at = [again[0] * launch, again[1] * launch, again[2] * launch];
325
+ }
326
+ else {
327
+ at = next;
328
+ }
329
+ continue;
330
+ }
331
+ // A touch: it sticks as the likeness says, to the most alike it touched.
332
+ let best = touched[0];
333
+ let bestLikeness = -1;
334
+ for (const other of touched) {
335
+ const likeness = feedLikeness_of(particle.plugins, other.particle.plugins, weights);
336
+ if (likeness > bestLikeness) {
337
+ best = other;
338
+ bestLikeness = likeness;
339
+ }
340
+ }
341
+ if (random() < Math.max(STICK_FLOOR, bestLikeness)) {
342
+ stuck = restingAgainst(best, at, particle.radius, random);
343
+ if (grid.touching(stuck, particle.radius - 1e-6).some((other) => other !== best && overlaps(stuck, particle.radius, other)))
344
+ stuck = null;
345
+ }
346
+ // Not this time: it is pushed off what it touched and wanders on,
347
+ // round the stranger toward its kin.
348
+ if (stuck === null) {
349
+ const off = restingAgainst(best, at, particle.radius, random);
350
+ const push = [off[0] - best.centre[0], off[1] - best.centre[1], off[2] - best.centre[2]];
351
+ const length = Math.max(1e-9, Math.hypot(push[0], push[1], push[2]));
352
+ at = [off[0] + (push[0] / length) * step, off[1] + (push[1] / length) * step, off[2] + (push[2] / length) * step];
353
+ }
354
+ }
355
+ // Out of steps: it sticks to its kin, a branch of its own.
356
+ centre = stuck ?? freeSpot_near(kin, particle.radius, grid, random);
357
+ }
358
+ settle(particle, index, centre);
359
+ if (index % 8 === 0)
360
+ onProgress(index / Math.max(1, particles.length));
361
+ });
362
+ onProgress(1);
363
+ return { positions, arrival };
364
+ }
365
+ /** Whether a ball at `at` overlaps a placed one (touching is not overlapping). */
366
+ function overlaps(at, radius, other) {
367
+ return Math.hypot(at[0] - other.centre[0], at[1] - other.centre[1], at[2] - other.centre[2]) < radius + other.particle.radius + STICK_GAP * 0.5;
368
+ }
369
+ /** A place touching `kin` where nothing else stands: tried round it, then further out. */
370
+ function freeSpot_near(kin, radius, grid, random) {
371
+ for (let ring = 0; ring < 8; ring++) {
372
+ for (let tries = 0; tries < 24; tries++) {
373
+ const d = direction_of(random);
374
+ const reach = radius + kin.particle.radius + STICK_GAP + ring * radius;
375
+ const at = [kin.centre[0] + d[0] * reach, kin.centre[1] + d[1] * reach, kin.centre[2] + d[2] * reach];
376
+ if (!grid.touching(at, radius).some((other) => overlaps(at, radius, other)))
377
+ return at;
378
+ }
379
+ }
380
+ const d = direction_of(random);
381
+ const reach = radius + kin.particle.radius + STICK_GAP + 8 * radius;
382
+ return [kin.centre[0] + d[0] * reach, kin.centre[1] + d[1] * reach, kin.centre[2] + d[2] * reach];
383
+ }
384
+ //# sourceMappingURL=accretion.js.map