@buley/hexgrid-3d 3.0.1 → 3.2.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 (209) hide show
  1. package/dist/HexGridEnhanced.d.ts +15 -0
  2. package/dist/HexGridEnhanced.d.ts.map +1 -0
  3. package/dist/HexGridEnhanced.js +1 -0
  4. package/dist/Snapshot.d.ts +594 -0
  5. package/dist/Snapshot.d.ts.map +1 -0
  6. package/dist/Snapshot.js +757 -0
  7. package/dist/adapters/DashAdapter.d.ts +18 -0
  8. package/dist/adapters/DashAdapter.d.ts.map +1 -0
  9. package/dist/adapters/DashAdapter.js +42 -0
  10. package/dist/adapters.d.ts +53 -0
  11. package/dist/adapters.d.ts.map +1 -0
  12. package/dist/adapters.js +14 -0
  13. package/dist/algorithms/AdvancedStatistics.d.ts +52 -0
  14. package/dist/algorithms/AdvancedStatistics.d.ts.map +1 -0
  15. package/dist/algorithms/AdvancedStatistics.js +307 -0
  16. package/dist/algorithms/BayesianStatistics.d.ts +86 -0
  17. package/dist/algorithms/BayesianStatistics.d.ts.map +1 -0
  18. package/dist/algorithms/BayesianStatistics.js +263 -0
  19. package/dist/algorithms/FlowField.d.ts +55 -0
  20. package/dist/algorithms/FlowField.d.ts.map +1 -0
  21. package/dist/algorithms/FlowField.js +80 -0
  22. package/dist/algorithms/FlowField3D.d.ts +166 -0
  23. package/dist/algorithms/FlowField3D.d.ts.map +1 -0
  24. package/dist/algorithms/FlowField3D.js +327 -0
  25. package/dist/algorithms/FluidEngineFactory.d.ts +15 -0
  26. package/dist/algorithms/FluidEngineFactory.d.ts.map +1 -0
  27. package/dist/algorithms/FluidEngineFactory.js +41 -0
  28. package/dist/algorithms/FluidSimulation.d.ts +41 -0
  29. package/dist/algorithms/FluidSimulation.d.ts.map +1 -0
  30. package/dist/algorithms/FluidSimulation.js +74 -0
  31. package/dist/algorithms/FluidSimulation3D.d.ts +137 -0
  32. package/dist/algorithms/FluidSimulation3D.d.ts.map +1 -0
  33. package/dist/algorithms/FluidSimulation3D.js +464 -0
  34. package/dist/algorithms/FluidSimulation3DGPU.d.ts +41 -0
  35. package/dist/algorithms/FluidSimulation3DGPU.d.ts.map +1 -0
  36. package/dist/algorithms/FluidSimulation3DGPU.js +328 -0
  37. package/dist/algorithms/FluidSimulationWebNN.d.ts +56 -0
  38. package/dist/algorithms/FluidSimulationWebNN.d.ts.map +1 -0
  39. package/dist/algorithms/FluidSimulationWebNN.js +84 -0
  40. package/dist/algorithms/GraphAlgorithms.d.ts +48 -0
  41. package/dist/algorithms/GraphAlgorithms.d.ts.map +1 -0
  42. package/dist/algorithms/GraphAlgorithms.js +122 -0
  43. package/dist/algorithms/OutlierDetection.d.ts +49 -0
  44. package/dist/algorithms/OutlierDetection.d.ts.map +1 -0
  45. package/dist/algorithms/OutlierDetection.js +284 -0
  46. package/dist/algorithms/ParticleSystem.d.ts +36 -0
  47. package/dist/algorithms/ParticleSystem.d.ts.map +1 -0
  48. package/dist/algorithms/ParticleSystem.js +59 -0
  49. package/dist/algorithms/ParticleSystem3D.d.ts +206 -0
  50. package/dist/algorithms/ParticleSystem3D.d.ts.map +1 -0
  51. package/dist/algorithms/ParticleSystem3D.js +371 -0
  52. package/dist/algorithms/index.d.ts +16 -0
  53. package/dist/algorithms/index.d.ts.map +1 -0
  54. package/{src/algorithms/index.ts → dist/algorithms/index.js} +0 -2
  55. package/dist/compat.d.ts +24 -0
  56. package/dist/compat.d.ts.map +1 -0
  57. package/dist/compat.js +88 -0
  58. package/dist/components/HexGrid.d.ts +5 -0
  59. package/dist/components/HexGrid.d.ts.map +1 -0
  60. package/dist/components/HexGrid.js +39 -0
  61. package/dist/components/NarrationOverlay.d.ts +16 -0
  62. package/dist/components/NarrationOverlay.d.ts.map +1 -0
  63. package/dist/components/NarrationOverlay.js +132 -0
  64. package/{src/components/index.ts → dist/components/index.d.ts} +1 -1
  65. package/dist/components/index.d.ts.map +1 -0
  66. package/dist/components/index.js +1 -0
  67. package/dist/features.d.ts +54 -0
  68. package/dist/features.d.ts.map +1 -0
  69. package/dist/features.js +74 -0
  70. package/dist/index.d.ts +12 -0
  71. package/dist/index.d.ts.map +1 -0
  72. package/dist/index.js +17 -0
  73. package/dist/lib/narration.d.ts +12 -0
  74. package/dist/lib/narration.d.ts.map +1 -0
  75. package/dist/lib/narration.js +8 -0
  76. package/dist/lib/stats-tracker.d.ts +7 -0
  77. package/dist/lib/stats-tracker.d.ts.map +1 -0
  78. package/dist/lib/stats-tracker.js +22 -0
  79. package/dist/lib/theme-colors.d.ts +7 -0
  80. package/dist/lib/theme-colors.d.ts.map +1 -0
  81. package/dist/lib/theme-colors.js +10 -0
  82. package/dist/math/HexCoordinates.d.ts +140 -0
  83. package/dist/math/HexCoordinates.d.ts.map +1 -0
  84. package/dist/math/HexCoordinates.js +741 -0
  85. package/dist/math/Matrix4.d.ts +9 -0
  86. package/dist/math/Matrix4.d.ts.map +1 -0
  87. package/dist/math/Matrix4.js +19 -0
  88. package/dist/math/Quaternion.d.ts +11 -0
  89. package/dist/math/Quaternion.d.ts.map +1 -0
  90. package/dist/math/Quaternion.js +23 -0
  91. package/dist/math/SpatialIndex.d.ts +34 -0
  92. package/dist/math/SpatialIndex.d.ts.map +1 -0
  93. package/dist/math/SpatialIndex.js +75 -0
  94. package/dist/math/Vector3.d.ts +110 -0
  95. package/dist/math/Vector3.d.ts.map +1 -0
  96. package/dist/math/Vector3.js +426 -0
  97. package/dist/math/index.d.ts +11 -0
  98. package/dist/math/index.d.ts.map +1 -0
  99. package/{src/math/index.ts → dist/math/index.js} +0 -1
  100. package/dist/note-adapter.d.ts +44 -0
  101. package/dist/note-adapter.d.ts.map +1 -0
  102. package/dist/note-adapter.js +86 -0
  103. package/dist/ontology-adapter.d.ts +13 -0
  104. package/dist/ontology-adapter.d.ts.map +1 -0
  105. package/dist/ontology-adapter.js +65 -0
  106. package/dist/stores/index.d.ts +2 -0
  107. package/dist/stores/index.d.ts.map +1 -0
  108. package/dist/stores/uiStore.d.ts +18 -0
  109. package/dist/stores/uiStore.d.ts.map +1 -0
  110. package/dist/stores/uiStore.js +77 -0
  111. package/dist/types/index.d.ts +4 -0
  112. package/dist/types/index.d.ts.map +1 -0
  113. package/dist/types/index.js +1 -0
  114. package/dist/types.d.ts +126 -0
  115. package/dist/types.d.ts.map +1 -0
  116. package/dist/types.js +4 -0
  117. package/dist/utils/image-utils.d.ts +13 -0
  118. package/dist/utils/image-utils.d.ts.map +1 -0
  119. package/dist/utils/image-utils.js +23 -0
  120. package/dist/wasm/HexGridWasmWrapper.d.ts +131 -0
  121. package/dist/wasm/HexGridWasmWrapper.d.ts.map +1 -0
  122. package/dist/wasm/HexGridWasmWrapper.js +610 -0
  123. package/dist/wasm/index.d.ts +7 -0
  124. package/dist/wasm/index.d.ts.map +1 -0
  125. package/{src/wasm/index.ts → dist/wasm/index.js} +0 -1
  126. package/dist/webgpu/WebGPUContext.d.ts +20 -0
  127. package/dist/webgpu/WebGPUContext.d.ts.map +1 -0
  128. package/dist/webgpu/WebGPUContext.js +60 -0
  129. package/dist/webnn/WebNNContext.d.ts +38 -0
  130. package/dist/webnn/WebNNContext.d.ts.map +1 -0
  131. package/dist/webnn/WebNNContext.js +66 -0
  132. package/dist/workers/hexgrid-math.d.ts +79 -0
  133. package/dist/workers/hexgrid-math.d.ts.map +1 -0
  134. package/dist/workers/hexgrid-math.js +136 -0
  135. package/dist/workers/hexgrid-worker.worker.d.ts +35 -0
  136. package/dist/workers/hexgrid-worker.worker.d.ts.map +1 -0
  137. package/dist/workers/hexgrid-worker.worker.js +2014 -0
  138. package/package.json +20 -7
  139. package/.eslintrc.json +0 -28
  140. package/build_log.txt +0 -500
  141. package/build_src_log.txt +0 -8
  142. package/examples/basic-usage.tsx +0 -52
  143. package/public/hexgrid-worker.js +0 -2475
  144. package/rust/Cargo.toml +0 -41
  145. package/rust/src/lib.rs +0 -740
  146. package/rust/src/math.rs +0 -574
  147. package/rust/src/spatial.rs +0 -245
  148. package/rust/src/statistics.rs +0 -496
  149. package/site/.eslintrc.json +0 -3
  150. package/site/DEPLOYMENT.md +0 -196
  151. package/site/INDEX.md +0 -127
  152. package/site/QUICK_START.md +0 -86
  153. package/site/README.md +0 -85
  154. package/site/SITE_SUMMARY.md +0 -180
  155. package/site/next.config.js +0 -12
  156. package/site/package.json +0 -26
  157. package/site/src/app/docs/page.tsx +0 -272
  158. package/site/src/app/examples/page.tsx +0 -151
  159. package/site/src/app/globals.css +0 -160
  160. package/site/src/app/layout.tsx +0 -39
  161. package/site/src/app/page.tsx +0 -235
  162. package/site/tsconfig.json +0 -29
  163. package/site/vercel.json +0 -6
  164. package/src/HexGridEnhanced.ts +0 -16
  165. package/src/Snapshot.ts +0 -1607
  166. package/src/adapters/DashAdapter.ts +0 -57
  167. package/src/adapters.ts +0 -63
  168. package/src/algorithms/AdvancedStatistics.ts +0 -362
  169. package/src/algorithms/BayesianStatistics.ts +0 -348
  170. package/src/algorithms/FlowField.ts +0 -150
  171. package/src/algorithms/FlowField3D.ts +0 -573
  172. package/src/algorithms/FluidEngineFactory.ts +0 -44
  173. package/src/algorithms/FluidSimulation.ts +0 -115
  174. package/src/algorithms/FluidSimulation3D.ts +0 -664
  175. package/src/algorithms/FluidSimulation3DGPU.ts +0 -402
  176. package/src/algorithms/FluidSimulationWebNN.ts +0 -141
  177. package/src/algorithms/GraphAlgorithms.ts +0 -191
  178. package/src/algorithms/OutlierDetection.ts +0 -425
  179. package/src/algorithms/ParticleSystem.ts +0 -95
  180. package/src/algorithms/ParticleSystem3D.ts +0 -567
  181. package/src/compat.ts +0 -96
  182. package/src/components/HexGrid.tsx +0 -61
  183. package/src/components/NarrationOverlay.tsx +0 -309
  184. package/src/features.ts +0 -125
  185. package/src/index.ts +0 -30
  186. package/src/lib/narration.ts +0 -17
  187. package/src/lib/stats-tracker.ts +0 -25
  188. package/src/lib/theme-colors.ts +0 -12
  189. package/src/math/HexCoordinates.ts +0 -863
  190. package/src/math/Matrix4.ts +0 -25
  191. package/src/math/Quaternion.ts +0 -37
  192. package/src/math/SpatialIndex.ts +0 -114
  193. package/src/math/Vector3.ts +0 -540
  194. package/src/note-adapter.ts +0 -132
  195. package/src/ontology-adapter.ts +0 -84
  196. package/src/stores/uiStore.ts +0 -85
  197. package/src/types/index.ts +0 -3
  198. package/src/types/shared-utils.d.ts +0 -10
  199. package/src/types/wgsl.d.ts +0 -4
  200. package/src/types.ts +0 -164
  201. package/src/utils/image-utils.ts +0 -28
  202. package/src/wasm/HexGridWasmWrapper.ts +0 -801
  203. package/src/webgpu/WebGPUContext.ts +0 -71
  204. package/src/webgpu/shaders/fluid_sim.wgsl +0 -140
  205. package/src/webnn/WebNNContext.ts +0 -99
  206. package/src/workers/hexgrid-math.ts +0 -182
  207. package/src/workers/hexgrid-worker.worker.ts +0 -2781
  208. package/tsconfig.json +0 -26
  209. /package/{src/stores/index.ts → dist/stores/index.js} +0 -0
@@ -0,0 +1,371 @@
1
+ /**
2
+ * 3D Particle System
3
+ *
4
+ * GPU-friendly particle physics for React Three Fiber InstancedMesh rendering.
5
+ * Supports forces, attractors, fluid coupling, and biometric visualization.
6
+ */
7
+ import { Vector3 } from '../math/Vector3';
8
+ /**
9
+ * 3D Particle System with GPU-friendly output
10
+ */
11
+ export class ParticleSystem3D {
12
+ constructor(config) {
13
+ this.particles = new Map();
14
+ this.particleOrder = [];
15
+ this.time = 0;
16
+ this.idCounter = 0;
17
+ this.maxParticles = config.maxParticles;
18
+ this.gravity = config.gravity ?? new Vector3(0, 0, 0);
19
+ this.drag = config.drag ?? 0.99;
20
+ this.boundsSphereRadius = config.boundsSphereRadius ?? Infinity;
21
+ this.boundsCenter = config.boundsCenter ?? new Vector3(0, 0, 0);
22
+ this.bounceFactor = config.bounceFactor ?? 0.5;
23
+ // Pre-allocate buffers (unless provided via config for zero-copy)
24
+ if (config.sharedBuffers) {
25
+ this.positionBuffer = config.sharedBuffers.positions;
26
+ this.colorBuffer = config.sharedBuffers.colors;
27
+ this.scaleBuffer = config.sharedBuffers.scales;
28
+ }
29
+ else {
30
+ this.positionBuffer = new Float32Array(this.maxParticles * 3);
31
+ this.colorBuffer = new Float32Array(this.maxParticles * 3);
32
+ this.scaleBuffer = new Float32Array(this.maxParticles);
33
+ }
34
+ }
35
+ /**
36
+ * Zero-Copy Binding: Inject shared buffers from WASM/Dash
37
+ */
38
+ setSharedBuffers(buffers) {
39
+ this.positionBuffer = buffers.positions;
40
+ this.colorBuffer = buffers.colors;
41
+ this.scaleBuffer = buffers.scales;
42
+ }
43
+ /**
44
+ * Emit particles at a position
45
+ */
46
+ emit(position, options = {}) {
47
+ const count = options.count ?? 1;
48
+ const emittedIds = [];
49
+ for (let i = 0; i < count; i++) {
50
+ if (this.particles.size >= this.maxParticles) {
51
+ // Remove oldest particle
52
+ const oldest = this.particleOrder.shift();
53
+ if (oldest) {
54
+ this.particles.delete(oldest);
55
+ }
56
+ }
57
+ const id = `p_${this.idCounter++}`;
58
+ const spread = options.velocitySpread ?? new Vector3(0, 0, 0);
59
+ const sizeSpread = options.sizeSpread ?? 0;
60
+ const lifeSpread = options.lifeSpread ?? 0;
61
+ const particle = {
62
+ id,
63
+ position: new Vector3(position.x, position.y, position.z),
64
+ velocity: new Vector3((options.velocity?.x ?? 0) + (Math.random() - 0.5) * 2 * spread.x, (options.velocity?.y ?? 0) + (Math.random() - 0.5) * 2 * spread.y, (options.velocity?.z ?? 0) + (Math.random() - 0.5) * 2 * spread.z),
65
+ acceleration: new Vector3(0, 0, 0),
66
+ color: options.color ?? [1, 1, 1],
67
+ size: (options.size ?? 1) + (Math.random() - 0.5) * 2 * sizeSpread,
68
+ life: (options.life ?? 5) + (Math.random() - 0.5) * 2 * lifeSpread,
69
+ maxLife: options.life ?? 5,
70
+ mass: options.mass ?? 1,
71
+ userData: options.userData,
72
+ heartRate: options.heartRate,
73
+ hrvValue: options.hrvValue,
74
+ pulseScale: 1,
75
+ };
76
+ this.particles.set(id, particle);
77
+ this.particleOrder.push(id);
78
+ emittedIds.push(id);
79
+ }
80
+ return emittedIds;
81
+ }
82
+ /**
83
+ * Add or update a persistent particle (for memory particles that don't expire)
84
+ */
85
+ setParticle(id, particle) {
86
+ const existing = this.particles.get(id);
87
+ if (existing) {
88
+ // Update existing
89
+ Object.assign(existing, particle);
90
+ existing.acceleration = new Vector3(0, 0, 0);
91
+ }
92
+ else {
93
+ // Add new
94
+ if (this.particles.size >= this.maxParticles) {
95
+ // Remove oldest non-persistent particle
96
+ for (let i = 0; i < this.particleOrder.length; i++) {
97
+ const oldId = this.particleOrder[i];
98
+ const oldParticle = this.particles.get(oldId);
99
+ if (oldParticle && oldParticle.life !== Infinity) {
100
+ this.particles.delete(oldId);
101
+ this.particleOrder.splice(i, 1);
102
+ break;
103
+ }
104
+ }
105
+ }
106
+ const newParticle = {
107
+ ...particle,
108
+ acceleration: new Vector3(0, 0, 0),
109
+ pulseScale: 1,
110
+ };
111
+ this.particles.set(id, newParticle);
112
+ this.particleOrder.push(id);
113
+ }
114
+ }
115
+ /**
116
+ * Remove a particle by ID
117
+ */
118
+ removeParticle(id) {
119
+ this.particles.delete(id);
120
+ const idx = this.particleOrder.indexOf(id);
121
+ if (idx >= 0) {
122
+ this.particleOrder.splice(idx, 1);
123
+ }
124
+ }
125
+ /**
126
+ * Get a particle by ID
127
+ */
128
+ getParticle(id) {
129
+ return this.particles.get(id);
130
+ }
131
+ /**
132
+ * Apply a force field to all particles
133
+ */
134
+ applyForceField(field) {
135
+ Array.from(this.particles.values()).forEach((particle) => {
136
+ const force = field(particle.position);
137
+ particle.acceleration.x += force.x / particle.mass;
138
+ particle.acceleration.y += force.y / particle.mass;
139
+ particle.acceleration.z += force.z / particle.mass;
140
+ });
141
+ }
142
+ /**
143
+ * Apply an attractor force
144
+ */
145
+ applyAttractor(center, strength, falloffRadius) {
146
+ Array.from(this.particles.values()).forEach((particle) => {
147
+ const dx = center.x - particle.position.x;
148
+ const dy = center.y - particle.position.y;
149
+ const dz = center.z - particle.position.z;
150
+ const dist = Math.sqrt(dx * dx + dy * dy + dz * dz);
151
+ if (dist > 0.001) {
152
+ const falloff = Math.max(0, 1 - dist / falloffRadius);
153
+ const force = (strength * falloff * falloff) / (dist * dist);
154
+ const invDist = 1 / dist;
155
+ particle.acceleration.x += (dx * invDist * force) / particle.mass;
156
+ particle.acceleration.y += (dy * invDist * force) / particle.mass;
157
+ particle.acceleration.z += (dz * invDist * force) / particle.mass;
158
+ }
159
+ });
160
+ }
161
+ /**
162
+ * Apply velocity from a fluid simulation
163
+ */
164
+ applyFluidVelocity(fluid, strength = 1) {
165
+ Array.from(this.particles.values()).forEach((particle) => {
166
+ const fluidVel = fluid.getVelocityAt(particle.position);
167
+ particle.velocity.x += fluidVel.x * strength;
168
+ particle.velocity.y += fluidVel.y * strength;
169
+ particle.velocity.z += fluidVel.z * strength;
170
+ });
171
+ }
172
+ /**
173
+ * Update all particles
174
+ */
175
+ update(dt) {
176
+ this.time += dt;
177
+ const deadParticles = [];
178
+ Array.from(this.particles.values()).forEach((particle) => {
179
+ // Apply gravity
180
+ particle.acceleration.x += this.gravity.x;
181
+ particle.acceleration.y += this.gravity.y;
182
+ particle.acceleration.z += this.gravity.z;
183
+ // Integrate velocity
184
+ particle.velocity.x += particle.acceleration.x * dt;
185
+ particle.velocity.y += particle.acceleration.y * dt;
186
+ particle.velocity.z += particle.acceleration.z * dt;
187
+ // Apply drag
188
+ particle.velocity.x *= this.drag;
189
+ particle.velocity.y *= this.drag;
190
+ particle.velocity.z *= this.drag;
191
+ // Integrate position
192
+ particle.position.x += particle.velocity.x * dt;
193
+ particle.position.y += particle.velocity.y * dt;
194
+ particle.position.z += particle.velocity.z * dt;
195
+ // Reset acceleration
196
+ particle.acceleration.x = 0;
197
+ particle.acceleration.y = 0;
198
+ particle.acceleration.z = 0;
199
+ // Sphere bounds collision
200
+ if (this.boundsSphereRadius < Infinity) {
201
+ const dx = particle.position.x - this.boundsCenter.x;
202
+ const dy = particle.position.y - this.boundsCenter.y;
203
+ const dz = particle.position.z - this.boundsCenter.z;
204
+ const dist = Math.sqrt(dx * dx + dy * dy + dz * dz);
205
+ if (dist > this.boundsSphereRadius) {
206
+ // Push back inside
207
+ const invDist = 1 / dist;
208
+ const nx = dx * invDist;
209
+ const ny = dy * invDist;
210
+ const nz = dz * invDist;
211
+ particle.position.x =
212
+ this.boundsCenter.x + nx * this.boundsSphereRadius * 0.99;
213
+ particle.position.y =
214
+ this.boundsCenter.y + ny * this.boundsSphereRadius * 0.99;
215
+ particle.position.z =
216
+ this.boundsCenter.z + nz * this.boundsSphereRadius * 0.99;
217
+ // Reflect velocity
218
+ const dot = particle.velocity.x * nx +
219
+ particle.velocity.y * ny +
220
+ particle.velocity.z * nz;
221
+ particle.velocity.x =
222
+ (particle.velocity.x - 2 * dot * nx) * this.bounceFactor;
223
+ particle.velocity.y =
224
+ (particle.velocity.y - 2 * dot * ny) * this.bounceFactor;
225
+ particle.velocity.z =
226
+ (particle.velocity.z - 2 * dot * nz) * this.bounceFactor;
227
+ }
228
+ }
229
+ // Update biometric pulse
230
+ if (particle.heartRate) {
231
+ const pulseFreq = particle.heartRate / 60; // Hz
232
+ const pulse = Math.sin(this.time * pulseFreq * Math.PI * 2);
233
+ particle.pulseScale = 1 + pulse * 0.15; // 15% size variation
234
+ }
235
+ // Decrease life (skip for Infinity life)
236
+ if (particle.life !== Infinity) {
237
+ particle.life -= dt;
238
+ if (particle.life <= 0) {
239
+ deadParticles.push(particle.id);
240
+ }
241
+ }
242
+ });
243
+ // Remove dead particles
244
+ deadParticles.forEach((id) => {
245
+ this.particles.delete(id);
246
+ const idx = this.particleOrder.indexOf(id);
247
+ if (idx >= 0) {
248
+ this.particleOrder.splice(idx, 1);
249
+ }
250
+ });
251
+ }
252
+ /**
253
+ * Get instance data for React Three Fiber InstancedMesh
254
+ */
255
+ getInstanceData() {
256
+ const count = this.particles.size;
257
+ const ids = [];
258
+ let i = 0;
259
+ const entries = Array.from(this.particles.entries());
260
+ for (let j = 0; j < entries.length && i < this.maxParticles; j++) {
261
+ const [id, particle] = entries[j];
262
+ // Position
263
+ this.positionBuffer[i * 3] = particle.position.x;
264
+ this.positionBuffer[i * 3 + 1] = particle.position.y;
265
+ this.positionBuffer[i * 3 + 2] = particle.position.z;
266
+ // Color with life-based alpha (encoded in color for now)
267
+ const lifeFactor = particle.life === Infinity
268
+ ? 1
269
+ : Math.min(1, particle.life / particle.maxLife);
270
+ this.colorBuffer[i * 3] = particle.color[0] * lifeFactor;
271
+ this.colorBuffer[i * 3 + 1] = particle.color[1] * lifeFactor;
272
+ this.colorBuffer[i * 3 + 2] = particle.color[2] * lifeFactor;
273
+ // Scale with pulse
274
+ this.scaleBuffer[i] = particle.size * (particle.pulseScale ?? 1);
275
+ ids.push(id);
276
+ i++;
277
+ }
278
+ return {
279
+ positions: this.positionBuffer.subarray(0, count * 3),
280
+ colors: this.colorBuffer.subarray(0, count * 3),
281
+ scales: this.scaleBuffer.subarray(0, count),
282
+ count,
283
+ ids,
284
+ };
285
+ }
286
+ /**
287
+ * Get all particles
288
+ */
289
+ getParticles() {
290
+ return Array.from(this.particles.values());
291
+ }
292
+ /**
293
+ * Get particle count
294
+ */
295
+ getCount() {
296
+ return this.particles.size;
297
+ }
298
+ /**
299
+ * Clear all particles
300
+ */
301
+ clear() {
302
+ this.particles.clear();
303
+ this.particleOrder = [];
304
+ }
305
+ /**
306
+ * Find particle nearest to a point
307
+ */
308
+ findNearest(point, maxDistance = Infinity) {
309
+ let nearest = null;
310
+ let nearestDist = maxDistance;
311
+ Array.from(this.particles.values()).forEach((particle) => {
312
+ const dist = particle.position.distanceTo(point);
313
+ if (dist < nearestDist) {
314
+ nearest = particle;
315
+ nearestDist = dist;
316
+ }
317
+ });
318
+ return nearest;
319
+ }
320
+ /**
321
+ * Find all particles within a radius
322
+ */
323
+ findWithinRadius(center, radius) {
324
+ const results = [];
325
+ const r2 = radius * radius;
326
+ Array.from(this.particles.values()).forEach((particle) => {
327
+ const dx = particle.position.x - center.x;
328
+ const dy = particle.position.y - center.y;
329
+ const dz = particle.position.z - center.z;
330
+ if (dx * dx + dy * dy + dz * dz <= r2) {
331
+ results.push(particle);
332
+ }
333
+ });
334
+ return results;
335
+ }
336
+ }
337
+ /**
338
+ * Pensieve-specific particle system with memory visualization presets
339
+ */
340
+ export class PensieveParticleSystem extends ParticleSystem3D {
341
+ constructor(maxParticles = 10000) {
342
+ super({
343
+ maxParticles,
344
+ gravity: new Vector3(0, -0.1, 0), // Gentle downward drift
345
+ drag: 0.995,
346
+ boundsSphereRadius: 50,
347
+ boundsCenter: new Vector3(0, 0, 0),
348
+ bounceFactor: 0.3,
349
+ });
350
+ }
351
+ /**
352
+ * Add a memory particle with reflection data
353
+ */
354
+ addMemoryParticle(id, position, color, options = {}) {
355
+ const size = 0.5 + (options.intensity ?? 0.5) * 0.5;
356
+ const ageFactor = options.ageFactor ?? 1;
357
+ this.setParticle(id, {
358
+ id,
359
+ position,
360
+ velocity: new Vector3((Math.random() - 0.5) * 0.5, (Math.random() - 0.5) * 0.5, (Math.random() - 0.5) * 0.5),
361
+ color: [color[0] * ageFactor, color[1] * ageFactor, color[2] * ageFactor],
362
+ size,
363
+ life: Infinity, // Memory particles don't expire
364
+ maxLife: Infinity,
365
+ mass: 1,
366
+ heartRate: options.heartRate,
367
+ hrvValue: options.hrvValue,
368
+ userData: options.userData,
369
+ });
370
+ }
371
+ }
@@ -0,0 +1,16 @@
1
+ /**
2
+ * Algorithms Module Exports
3
+ *
4
+ * @module algorithms
5
+ */
6
+ export * from './GraphAlgorithms';
7
+ export * from './FlowField';
8
+ export * from './ParticleSystem';
9
+ export * from './FluidSimulation';
10
+ export * from './AdvancedStatistics';
11
+ export * from './BayesianStatistics';
12
+ export * from './OutlierDetection';
13
+ export * from './FluidSimulation3D';
14
+ export * from './ParticleSystem3D';
15
+ export * from './FlowField3D';
16
+ //# sourceMappingURL=index.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../../src/algorithms/index.ts"],"names":[],"mappings":"AAAA;;;;GAIG;AAGH,cAAc,mBAAmB,CAAC;AAClC,cAAc,aAAa,CAAC;AAC5B,cAAc,kBAAkB,CAAC;AACjC,cAAc,mBAAmB,CAAC;AAClC,cAAc,sBAAsB,CAAC;AACrC,cAAc,sBAAsB,CAAC;AACrC,cAAc,oBAAoB,CAAC;AAGnC,cAAc,qBAAqB,CAAC;AACpC,cAAc,oBAAoB,CAAC;AACnC,cAAc,eAAe,CAAC"}
@@ -3,7 +3,6 @@
3
3
  *
4
4
  * @module algorithms
5
5
  */
6
-
7
6
  // 2D algorithms (existing)
8
7
  export * from './GraphAlgorithms';
9
8
  export * from './FlowField';
@@ -12,7 +11,6 @@ export * from './FluidSimulation';
12
11
  export * from './AdvancedStatistics';
13
12
  export * from './BayesianStatistics';
14
13
  export * from './OutlierDetection';
15
-
16
14
  // 3D algorithms (new - for Pensieve)
17
15
  export * from './FluidSimulation3D';
18
16
  export * from './ParticleSystem3D';
@@ -0,0 +1,24 @@
1
+ /**
2
+ * Backward compatibility layer for Photo and GridItem
3
+ *
4
+ * Provides conversion utilities to ensure existing Photo-based code
5
+ * continues to work while new code can use GridItem.
6
+ */
7
+ import type { Photo, GridItem } from './types';
8
+ /**
9
+ * Convert Photo to GridItem for backward compatibility
10
+ */
11
+ export declare function photoToGridItem(photo: Photo): GridItem<Photo>;
12
+ /**
13
+ * Convert GridItem back to Photo if possible
14
+ */
15
+ export declare function gridItemToPhoto(item: GridItem<Photo>): Photo | null;
16
+ /**
17
+ * Convert an array of Photos to GridItems
18
+ */
19
+ export declare function photosToGridItems(photos: Photo[]): GridItem<Photo>[];
20
+ /**
21
+ * Convert an array of GridItems to Photos (filtering out non-photo items)
22
+ */
23
+ export declare function gridItemsToPhotos(items: GridItem<Photo>[]): Photo[];
24
+ //# sourceMappingURL=compat.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"compat.d.ts","sourceRoot":"","sources":["../src/compat.ts"],"names":[],"mappings":"AAAA;;;;;GAKG;AAEH,OAAO,KAAK,EAAE,KAAK,EAAE,QAAQ,EAAE,MAAM,SAAS,CAAC;AAE/C;;GAEG;AACH,wBAAgB,eAAe,CAAC,KAAK,EAAE,KAAK,GAAG,QAAQ,CAAC,KAAK,CAAC,CA4B7D;AAED;;GAEG;AACH,wBAAgB,eAAe,CAAC,IAAI,EAAE,QAAQ,CAAC,KAAK,CAAC,GAAG,KAAK,GAAG,IAAI,CAkCnE;AAED;;GAEG;AACH,wBAAgB,iBAAiB,CAAC,MAAM,EAAE,KAAK,EAAE,GAAG,QAAQ,CAAC,KAAK,CAAC,EAAE,CAEpE;AAED;;GAEG;AACH,wBAAgB,iBAAiB,CAAC,KAAK,EAAE,QAAQ,CAAC,KAAK,CAAC,EAAE,GAAG,KAAK,EAAE,CAInE"}
package/dist/compat.js ADDED
@@ -0,0 +1,88 @@
1
+ /**
2
+ * Backward compatibility layer for Photo and GridItem
3
+ *
4
+ * Provides conversion utilities to ensure existing Photo-based code
5
+ * continues to work while new code can use GridItem.
6
+ */
7
+ /**
8
+ * Convert Photo to GridItem for backward compatibility
9
+ */
10
+ export function photoToGridItem(photo) {
11
+ return {
12
+ id: photo.id,
13
+ type: 'photo',
14
+ imageUrl: photo.imageUrl,
15
+ thumbnailUrl: photo.thumbnailUrl,
16
+ title: photo.title,
17
+ alt: photo.alt,
18
+ description: photo.description,
19
+ category: photo.category,
20
+ data: photo,
21
+ // Map all Photo fields
22
+ url: photo.imageUrl,
23
+ userId: photo.userId,
24
+ username: photo.username,
25
+ videoUrl: photo.videoUrl,
26
+ platform: photo.platform,
27
+ author: photo.author,
28
+ authorUrl: photo.authorUrl,
29
+ likes: photo.likes,
30
+ views: photo.views,
31
+ comments: photo.comments,
32
+ dominantColor: photo.dominantColor,
33
+ source: photo.source,
34
+ sourceUrl: photo.sourceUrl,
35
+ createdAt: photo.createdAt,
36
+ velocity: photo.velocity,
37
+ };
38
+ }
39
+ /**
40
+ * Convert GridItem back to Photo if possible
41
+ */
42
+ export function gridItemToPhoto(item) {
43
+ // If item contains original Photo data, return it
44
+ if (item.type === 'photo' && item.data) {
45
+ return item.data;
46
+ }
47
+ // Fallback: construct Photo from GridItem fields
48
+ if (item.imageUrl || item.url) {
49
+ return {
50
+ id: item.id,
51
+ title: item.title ?? '',
52
+ alt: item.alt ?? item.title ?? '',
53
+ imageUrl: item.imageUrl || item.url || '',
54
+ category: item.category ?? 'uncategorized',
55
+ description: item.description,
56
+ source: item.source || 'unknown',
57
+ sourceUrl: item.sourceUrl,
58
+ createdAt: item.createdAt,
59
+ thumbnailUrl: item.thumbnailUrl,
60
+ userId: item.userId,
61
+ username: item.username,
62
+ videoUrl: item.videoUrl,
63
+ platform: item.platform,
64
+ author: item.author,
65
+ authorUrl: item.authorUrl,
66
+ likes: item.likes,
67
+ views: item.views,
68
+ comments: item.comments,
69
+ dominantColor: item.dominantColor,
70
+ velocity: item.velocity,
71
+ };
72
+ }
73
+ return null;
74
+ }
75
+ /**
76
+ * Convert an array of Photos to GridItems
77
+ */
78
+ export function photosToGridItems(photos) {
79
+ return photos.map(photoToGridItem);
80
+ }
81
+ /**
82
+ * Convert an array of GridItems to Photos (filtering out non-photo items)
83
+ */
84
+ export function gridItemsToPhotos(items) {
85
+ return items
86
+ .map(gridItemToPhoto)
87
+ .filter((photo) => photo !== null);
88
+ }
@@ -0,0 +1,5 @@
1
+ import React from 'react';
2
+ import { HexGridProps } from '../types';
3
+ export declare function HexGrid(props: HexGridProps): React.JSX.Element;
4
+ export default HexGrid;
5
+ //# sourceMappingURL=HexGrid.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"HexGrid.d.ts","sourceRoot":"","sources":["../../src/components/HexGrid.tsx"],"names":[],"mappings":"AACA,OAAO,KAAsC,MAAM,OAAO,CAAC;AAE3D,OAAO,EAAE,YAAY,EAAE,MAAM,UAAU,CAAC;AAExC,wBAAgB,OAAO,CAAC,KAAK,EAAE,YAAY,GAAG,KAAK,CAAC,GAAG,CAAC,OAAO,CAqD9D;AAED,eAAe,OAAO,CAAC"}
@@ -0,0 +1,39 @@
1
+ import { jsxs as _jsxs, jsx as _jsx } from "react/jsx-runtime";
2
+ import { useEffect, useRef, useState } from 'react';
3
+ import { FluidEngineFactory } from '../algorithms/FluidEngineFactory';
4
+ export function HexGrid(props) {
5
+ const canvasRef = useRef(null);
6
+ const [engine, setEngine] = useState(null);
7
+ const [error, setError] = useState(null);
8
+ useEffect(() => {
9
+ // Initialize Fluid Engine
10
+ const initEngine = async () => {
11
+ try {
12
+ const fluidEngine = await FluidEngineFactory.create({
13
+ width: 64,
14
+ height: 64,
15
+ depth: 64,
16
+ viscosity: 0.0001,
17
+ diffusion: 0.00001
18
+ });
19
+ setEngine(fluidEngine);
20
+ }
21
+ catch (err) {
22
+ console.error("Failed to init fluid engine", err);
23
+ setError(err instanceof Error ? err.message : String(err));
24
+ }
25
+ };
26
+ initEngine();
27
+ return () => {
28
+ // Cleanup if engine has cleanup method
29
+ if (engine && 'clear' in engine) {
30
+ engine.clear();
31
+ }
32
+ };
33
+ }, []);
34
+ if (error) {
35
+ return _jsxs("div", { className: "text-red-500", children: ["Error initializing simulation: ", error] });
36
+ }
37
+ return (_jsxs("div", { className: "hexgrid-container", style: { width: '100%', height: '100%', position: 'relative' }, children: [_jsx("canvas", { ref: canvasRef, width: 800, height: 600, style: { width: '100%', height: '100%' } }), _jsxs("div", { style: { position: 'absolute', top: 10, left: 10, background: 'rgba(0,0,0,0.5)', color: 'white', padding: '5px', pointerEvents: 'none' }, children: ["Engine: ", engine ? engine.constructor.name : 'Initializing...'] })] }));
38
+ }
39
+ export default HexGrid;
@@ -0,0 +1,16 @@
1
+ /**
2
+ * Narration Overlay Component
3
+ *
4
+ * Displays play-by-play narration messages with sparklines in a NOC dashboard style.
5
+ */
6
+ import React from 'react';
7
+ import { NarrationMessage } from '@/lib/narration';
8
+ import { StatsTracker } from '@/lib/stats-tracker';
9
+ export interface NarrationOverlayProps {
10
+ messages: NarrationMessage[];
11
+ statsTracker: StatsTracker | null;
12
+ isVisible: boolean;
13
+ onClose: () => void;
14
+ }
15
+ export declare const NarrationOverlay: React.FC<NarrationOverlayProps>;
16
+ //# sourceMappingURL=NarrationOverlay.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"NarrationOverlay.d.ts","sourceRoot":"","sources":["../../src/components/NarrationOverlay.tsx"],"names":[],"mappings":"AAAA;;;;GAIG;AAEH,OAAO,KAA4B,MAAM,OAAO,CAAC;AACjD,OAAO,EAAE,gBAAgB,EAAE,MAAM,iBAAiB,CAAC;AACnD,OAAO,EAAE,YAAY,EAAE,MAAM,qBAAqB,CAAC;AAGnD,MAAM,WAAW,qBAAqB;IACpC,QAAQ,EAAE,gBAAgB,EAAE,CAAC;IAC7B,YAAY,EAAE,YAAY,GAAG,IAAI,CAAC;IAClC,SAAS,EAAE,OAAO,CAAC;IACnB,OAAO,EAAE,MAAM,IAAI,CAAC;CACrB;AAED,eAAO,MAAM,gBAAgB,EAAE,KAAK,CAAC,EAAE,CAAC,qBAAqB,CAkS5D,CAAC"}