@descix/frqtl-node 0.0.0-stage → 0.6.0-p0.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/CLAUDE.md +87 -0
- package/README.md +84 -2
- package/dist/dist-manifest.json +218 -0
- package/dist/eyes/index.js +109 -0
- package/dist/fat/pkg-node/egpt_wasm.js +1277 -0
- package/dist/fat/pkg-node/egpt_wasm_bg.wasm +0 -0
- package/dist/fat/pkg-node/package.json +12 -0
- package/dist/frqtl/assets/vendor/chroma.mjs +64 -0
- package/dist/frqtl/compat/boot-node.js +34 -0
- package/dist/frqtl/compat/engine.js +127 -0
- package/dist/frqtl/compat/package-root.js +24 -0
- package/dist/frqtl/compat/providers/wasm-engine.js +2501 -0
- package/dist/frqtl/compat/providers/wasm-load-browser.js +134 -0
- package/dist/frqtl/compat/providers/wasm-load-node.js +59 -0
- package/dist/frqtl/compat/renderer/FieldBuilder.js +145 -0
- package/dist/frqtl/compat/renderer/Filters.js +163 -0
- package/dist/frqtl/compat/renderer/RenderFamily.js +85 -0
- package/dist/frqtl/compat/renderer/RenderMesh.js +100 -0
- package/dist/frqtl/compat/renderer/RenderShape.js +154 -0
- package/dist/frqtl/compat/renderer/camera2d-geometry.js +183 -0
- package/dist/frqtl/compat/renderer/captureStill-common.js +259 -0
- package/dist/frqtl/compat/renderer/display-slot.js +96 -0
- package/dist/frqtl/compat/renderer/lo-drawn-center.js +231 -0
- package/dist/frqtl/compat/renderer/orbit-bag.js +216 -0
- package/dist/frqtl/compat/renderer/providers/godrays-layer.js +213 -0
- package/dist/frqtl/compat/renderer/providers/index.js +22 -0
- package/dist/frqtl/compat/renderer/providers/p5-provider.js +861 -0
- package/dist/frqtl/compat/renderer/providers/three-camera-contract.js +160 -0
- package/dist/frqtl/compat/renderer/providers/three-camera-geometry.js +571 -0
- package/dist/frqtl/compat/renderer/providers/three-provider.js +2474 -0
- package/dist/frqtl/compat/renderer/renderCapabilities-common.js +186 -0
- package/dist/frqtl/compat/renderer/renderer-provider-contract.js +238 -0
- package/dist/frqtl/compat/renderer/unprojectStill.js +172 -0
- package/dist/frqtl/compat/vendor.js +196 -0
- package/dist/frqtl/node-entry.js +17 -0
- package/dist/frqtl/objects/FrqtlApp.js +2922 -0
- package/dist/frqtl/objects/ObjectFactory.js +297 -0
- package/dist/frqtl/objects/RecipeContext.js +322 -0
- package/dist/frqtl/objects/collectors/DataCollector.js +116 -0
- package/dist/frqtl/objects/constants/WallBehaviors.js +178 -0
- package/dist/frqtl/objects/geometry/SlabFace.js +258 -0
- package/dist/frqtl/objects/instruments/capture-host.js +453 -0
- package/dist/frqtl/objects/instruments/capture.js +711 -0
- package/dist/frqtl/objects/instruments/hosted-eyes.js +985 -0
- package/dist/frqtl/objects/kinds-entry.js +14 -0
- package/dist/frqtl/objects/kinds.js +190 -0
- package/dist/frqtl/objects/objects/Box.js +273 -0
- package/dist/frqtl/objects/objects/Bullet.js +155 -0
- package/dist/frqtl/objects/objects/CircuitGate.js +380 -0
- package/dist/frqtl/objects/objects/CircuitProbe.js +214 -0
- package/dist/frqtl/objects/objects/DirectedTunnel.js +412 -0
- package/dist/frqtl/objects/objects/EgptFractal.js +164 -0
- package/dist/frqtl/objects/objects/LightSource.js +354 -0
- package/dist/frqtl/objects/objects/QuantumEmitter.js +760 -0
- package/dist/frqtl/objects/objects/Tube.js +471 -0
- package/dist/frqtl/objects/objects/absorbRadiation.js +310 -0
- package/dist/frqtl/objects/objects/actionCompiler.js +1747 -0
- package/dist/frqtl/objects/objects/controlAction.js +89 -0
- package/dist/frqtl/objects/objects/controlBind.js +278 -0
- package/dist/frqtl/objects/objects/directedRedirectProgram.js +120 -0
- package/dist/frqtl/objects/objects/emitterProgram.js +209 -0
- package/dist/frqtl/objects/objects/frqtl-control-slider.js +197 -0
- package/dist/frqtl/objects/objects/frqtl-control-sync.js +272 -0
- package/dist/frqtl/objects/objects/frqtl-control-widgets.js +219 -0
- package/dist/frqtl/objects/objects/frqtl-control-write-queue.js +174 -0
- package/dist/frqtl/objects/objects/makeControlsForObject.js +824 -0
- package/dist/frqtl/objects/objects/makeControlsForRenderSurface.js +161 -0
- package/dist/frqtl/objects/objects/slitLinerScatter.js +263 -0
- package/dist/frqtl/objects/objects/sustainedSource.js +299 -0
- package/dist/frqtl/objects/objects/tagger.js +228 -0
- package/dist/frqtl/objects/schema/engine-scopes.js +469 -0
- package/dist/frqtl/objects/schema/index.js +256 -0
- package/dist/frqtl/objects/schema/scopes.js +457 -0
- package/dist/frqtl/objects/schema/validate-descriptor.js +49 -0
- package/dist/frqtl/objects/schema/valueNormalizer.js +366 -0
- package/dist/frqtl/objects/setup/_collisionMatrixLanes.js +66 -0
- package/dist/frqtl/objects/setup/_setupOptions.js +118 -0
- package/dist/frqtl/objects/setup/_worldInit.js +162 -0
- package/dist/frqtl/objects/setup/setupBlackbodySubstrate.js +242 -0
- package/dist/frqtl/objects/setup/setupCircuitBasic.js +447 -0
- package/dist/frqtl/objects/setup/setupCollisionMatrix.js +188 -0
- package/dist/frqtl/objects/setup/setupConeEmitter3D.js +251 -0
- package/dist/frqtl/objects/setup/setupDoubleSlit.js +327 -0
- package/dist/frqtl/objects/setup/setupDoubleSlit_Laser.js +229 -0
- package/dist/frqtl/objects/setup/setupEmpty.js +59 -0
- package/dist/frqtl/objects/setup/setupFxSmoke.js +209 -0
- package/dist/frqtl/objects/setup/setupG1Race.js +80 -0
- package/dist/frqtl/objects/setup/setupG2Sweep.js +89 -0
- package/dist/frqtl/objects/setup/setupG3Collide.js +177 -0
- package/dist/frqtl/objects/setup/setupLightSourceLab.js +280 -0
- package/dist/frqtl/objects/setup/setupOscillator.js +68 -0
- package/dist/frqtl/objects/setup/setupParticleWalk.js +93 -0
- package/dist/frqtl/objects/setup/setupParticleWalk3D.js +133 -0
- package/dist/frqtl/objects/setup/setupSphereEmitter3D.js +1259 -0
- package/dist/frqtl/objects/setup/setupTraceCircuit.js +239 -0
- package/dist/frqtl/objects/setup/setupTunnelLab.js +242 -0
- package/dist/frqtl/objects/setup/setupTunnelPointExit.js +306 -0
- package/dist/frqtl/objects/setup/setupWaveInterference.js +178 -0
- package/dist/frqtl/objects/v1-replacements.js +30 -0
- package/dist/frqtl/package-core.js +23 -0
- package/dist/frqtl/parts/CameraControls.js +643 -0
- package/dist/frqtl/parts/CameraPath.js +575 -0
- package/dist/frqtl/parts/CollisionActions.js +35 -0
- package/dist/frqtl/parts/CollisionTypes.js +31 -0
- package/dist/frqtl/parts/DetectorWall.js +496 -0
- package/dist/frqtl/parts/FrqtlControlOverlay.js +227 -0
- package/dist/frqtl/parts/FrqtlControlsPanel.js +415 -0
- package/dist/frqtl/parts/FrqtlVision.js +818 -0
- package/dist/frqtl/parts/GraphingDetectorWall.js +490 -0
- package/dist/frqtl/parts/LargeObject.js +406 -0
- package/dist/frqtl/parts/LightColor.js +255 -0
- package/dist/frqtl/parts/LiveChart.js +285 -0
- package/dist/frqtl/parts/LogicGate.js +720 -0
- package/dist/frqtl/parts/OvenBox.js +612 -0
- package/dist/frqtl/parts/PointSource.js +763 -0
- package/dist/frqtl/parts/Rectangle.js +200 -0
- package/dist/frqtl/parts/SlitLightSource.js +234 -0
- package/dist/frqtl/parts/SlitScreen.js +628 -0
- package/dist/frqtl/parts/SphereEmitter.js +946 -0
- package/dist/frqtl/parts/Trace.js +508 -0
- package/dist/frqtl/parts/Tunnel.js +1057 -0
- package/dist/frqtl/parts/Wall.js +1211 -0
- package/dist/frqtl/parts/index.js +33 -0
- package/dist/frqtl/scenes/absorbing-wall-3d.js +33 -0
- package/dist/frqtl/scenes/absorbing-wall.js +32 -0
- package/dist/frqtl/scenes/atomic-model.js +88 -0
- package/dist/frqtl/scenes/big-bang.js +46 -0
- package/dist/frqtl/scenes/blackbody.js +81 -0
- package/dist/frqtl/scenes/circuit-sat.js +127 -0
- package/dist/frqtl/scenes/collision-matrix-3d.js +107 -0
- package/dist/frqtl/scenes/counting-wall-3d.js +36 -0
- package/dist/frqtl/scenes/counting-wall.js +38 -0
- package/dist/frqtl/scenes/double-slit.js +31 -0
- package/dist/frqtl/scenes/dse-one-emitter.js +196 -0
- package/dist/frqtl/scenes/dse-one-slit.js +114 -0
- package/dist/frqtl/scenes/dse-photoelectric.js +70 -0
- package/dist/frqtl/scenes/dse-tunnel-rebuild.js +244 -0
- package/dist/frqtl/scenes/dse-two-emitters.js +196 -0
- package/dist/frqtl/scenes/dse-two-slits.js +132 -0
- package/dist/frqtl/scenes/empty.js +14 -0
- package/dist/frqtl/scenes/laser-buildup.js +49 -0
- package/dist/frqtl/scenes/mirror-3d.js +56 -0
- package/dist/frqtl/scenes/mirror-route.js +140 -0
- package/dist/frqtl/scenes/mirror.js +38 -0
- package/dist/frqtl/scenes/omni-3d.js +27 -0
- package/dist/frqtl/scenes/omni-source.js +22 -0
- package/dist/frqtl/scenes/self-interference.js +39 -0
- package/dist/frqtl/scenes/smoking-gun.js +122 -0
- package/dist/frqtl/scenes/straight-walk.js +22 -0
- package/dist/frqtl/scenes/sun.js +39 -0
- package/dist/frqtl/scenes/two-source.js +37 -0
- package/dist/frqtl/scenes/wave.js +26 -0
- package/dist/shim/bundle/frqnb.js +112 -0
- package/dist/shim/bundle/index.js +121 -0
- package/dist/shim/bundle/indexHtml.js +107 -0
- package/dist/shim/bundle/manifest.js +95 -0
- package/dist/shim/bundle/zip.js +243 -0
- package/dist/shim/bus.js +67 -0
- package/dist/shim/controls/index.js +627 -0
- package/dist/shim/controls/registry.js +274 -0
- package/dist/shim/engine/artifact-shell.js +212 -0
- package/dist/shim/engine/boot-phases.js +44 -0
- package/dist/shim/engine/engine-stack-boot.js +59 -0
- package/dist/shim/engine/router.js +692 -0
- package/dist/shim/experiment-frame/index.js +296 -0
- package/dist/shim/expr/ast-schema.js +369 -0
- package/dist/shim/field-descriptor/index.js +326 -0
- package/dist/shim/frame-data/index.js +224 -0
- package/dist/shim/index.js +67 -0
- package/dist/shim/notebook/canvas-guard.js +82 -0
- package/dist/shim/notebook/catalog.js +35 -0
- package/dist/shim/notebook/format.js +736 -0
- package/dist/shim/notebook/frqtl-setups-importmap.js +81 -0
- package/dist/shim/notebook/kernel.js +672 -0
- package/dist/shim/notebook/knob.js +151 -0
- package/dist/shim/notebook/module-resolver.js +260 -0
- package/dist/shim/notebook/notebook-knobs.js +65 -0
- package/dist/shim/notebook/produced-bindings.js +67 -0
- package/dist/shim/notebook/realm-registry.js +121 -0
- package/dist/shim/notebook/realm-transport.js +73 -0
- package/dist/shim/notebook/setup-builder.js +510 -0
- package/dist/shim/notebook/store.js +159 -0
- package/dist/shim/notebook/vendor-importmap.js +134 -0
- package/dist/shim/notebook/view-builder.js +189 -0
- package/dist/shim/notebook/view-ctx.js +100 -0
- package/dist/shim/notebook/view-handle.js +202 -0
- package/dist/shim/notebook/warmup.js +102 -0
- package/dist/shim/package.json +4 -0
- package/dist/shim/page-params/index.js +214 -0
- package/dist/shim/project/identity.js +112 -0
- package/dist/shim/project/index.js +19 -0
- package/dist/shim/project/link.js +402 -0
- package/dist/shim/project/node-specifier-hook.mjs +35 -0
- package/dist/shim/project/register-node.mjs +17 -0
- package/dist/shim/project/specifiers.js +106 -0
- package/dist/shim/registry/copy-gate.js +110 -0
- package/dist/shim/registry/exhibits.js +455 -0
- package/dist/shim/registry/experiments.js +215 -0
- package/dist/shim/registry/index.js +19 -0
- package/dist/shim/registry/scene-source.js +157 -0
- package/dist/shim/registry/walkthrough.js +807 -0
- package/dist/shim/render/capture-envelope.js +279 -0
- package/dist/shim/render/heat-colormap.js +92 -0
- package/dist/shim/render/render-stages.js +855 -0
- package/dist/shim/render/sun-look.js +33 -0
- package/dist/shim/render-state/apply.js +262 -0
- package/dist/shim/render-state/index.js +74 -0
- package/dist/shim/rpc/index.js +207 -0
- package/dist/shim/runtime/index.js +1023 -0
- package/dist/shim/storage/boot.js +69 -0
- package/dist/shim/storage/index.js +169 -0
- package/dist/shim/storage/local-storage-provider.js +230 -0
- package/dist/shim/storage/make-namespace-store.js +132 -0
- package/dist/shim/storage/modules.js +249 -0
- package/dist/shim/storage/projects.js +150 -0
- package/llms.txt +12 -0
- package/package.json +62 -4
|
@@ -0,0 +1,200 @@
|
|
|
1
|
+
/* Copyright 2023-2026 by Essam Abadir */
|
|
2
|
+
|
|
3
|
+
/**
|
|
4
|
+
* Rectangle — Spatial rectangle with auto-computed edges.
|
|
5
|
+
*
|
|
6
|
+
* Supports two construction modes:
|
|
7
|
+
* - Centered (isCentered=true): x,y is the CENTER; left/top/right/bottom auto-computed
|
|
8
|
+
* - Non-centered (isCentered=false): x,y is TOP-LEFT; center auto-computed
|
|
9
|
+
*
|
|
10
|
+
* All edge properties (left, top, right, bottom, x, y) are linked via
|
|
11
|
+
* getters/setters — changing any one updates the others consistently.
|
|
12
|
+
*
|
|
13
|
+
* The SOLE Rectangle authority: the WASM provider wrapper (compat/providers/wasm-engine.js) and
|
|
14
|
+
* every part import it.
|
|
15
|
+
*/
|
|
16
|
+
|
|
17
|
+
|
|
18
|
+
function Rectangle(x, y, w, h, data, isCentered) {
|
|
19
|
+
if (isCentered === undefined) isCentered = true;
|
|
20
|
+
this.is_centered = isCentered;
|
|
21
|
+
this.data = data || null;
|
|
22
|
+
this.w = w;
|
|
23
|
+
this.h = h;
|
|
24
|
+
|
|
25
|
+
if (isCentered) {
|
|
26
|
+
// x,y is the center
|
|
27
|
+
this._x = x;
|
|
28
|
+
this._y = y;
|
|
29
|
+
this._left = x - w / 2;
|
|
30
|
+
this._right = x + w / 2;
|
|
31
|
+
this._top = y - h / 2;
|
|
32
|
+
this._bottom = y + h / 2;
|
|
33
|
+
} else {
|
|
34
|
+
// x,y is the top-left corner
|
|
35
|
+
this._x = x + w / 2;
|
|
36
|
+
this._y = y + h / 2;
|
|
37
|
+
this._left = x;
|
|
38
|
+
this._right = x + w;
|
|
39
|
+
this._top = y;
|
|
40
|
+
this._bottom = y + h;
|
|
41
|
+
}
|
|
42
|
+
this.r = w / 2;
|
|
43
|
+
}
|
|
44
|
+
|
|
45
|
+
// ── Linked property accessors ────────────────────────────────────────
|
|
46
|
+
|
|
47
|
+
Object.defineProperty(Rectangle.prototype, 'x', {
|
|
48
|
+
get: function () { return this._x; },
|
|
49
|
+
set: function (val) {
|
|
50
|
+
this._x = val;
|
|
51
|
+
this._left = val - this.w / 2;
|
|
52
|
+
this._right = val + this.w / 2;
|
|
53
|
+
}
|
|
54
|
+
});
|
|
55
|
+
|
|
56
|
+
Object.defineProperty(Rectangle.prototype, 'y', {
|
|
57
|
+
get: function () { return this._y; },
|
|
58
|
+
set: function (val) {
|
|
59
|
+
this._y = val;
|
|
60
|
+
this._top = val - this.h / 2;
|
|
61
|
+
this._bottom = val + this.h / 2;
|
|
62
|
+
}
|
|
63
|
+
});
|
|
64
|
+
|
|
65
|
+
Object.defineProperty(Rectangle.prototype, 'left', {
|
|
66
|
+
get: function () { return this._left; },
|
|
67
|
+
set: function (val) {
|
|
68
|
+
this._left = val;
|
|
69
|
+
this._x = val + this.w / 2;
|
|
70
|
+
this._right = val + this.w;
|
|
71
|
+
}
|
|
72
|
+
});
|
|
73
|
+
|
|
74
|
+
Object.defineProperty(Rectangle.prototype, 'right', {
|
|
75
|
+
get: function () { return this._right; },
|
|
76
|
+
set: function (val) {
|
|
77
|
+
this._right = val;
|
|
78
|
+
this._x = val - this.w / 2;
|
|
79
|
+
this._left = val - this.w;
|
|
80
|
+
}
|
|
81
|
+
});
|
|
82
|
+
|
|
83
|
+
Object.defineProperty(Rectangle.prototype, 'top', {
|
|
84
|
+
get: function () { return this._top; },
|
|
85
|
+
set: function (val) {
|
|
86
|
+
this._top = val;
|
|
87
|
+
this._y = val + this.h / 2;
|
|
88
|
+
this._bottom = val + this.h;
|
|
89
|
+
}
|
|
90
|
+
});
|
|
91
|
+
|
|
92
|
+
Object.defineProperty(Rectangle.prototype, 'bottom', {
|
|
93
|
+
get: function () { return this._bottom; },
|
|
94
|
+
set: function (val) {
|
|
95
|
+
this._bottom = val;
|
|
96
|
+
this._y = val - this.h / 2;
|
|
97
|
+
this._top = val - this.h;
|
|
98
|
+
}
|
|
99
|
+
});
|
|
100
|
+
|
|
101
|
+
Object.defineProperty(Rectangle.prototype, 'area', {
|
|
102
|
+
get: function () { return this.w * this.h; }
|
|
103
|
+
});
|
|
104
|
+
|
|
105
|
+
// ── Spatial queries ──────────────────────────────────────────────────
|
|
106
|
+
|
|
107
|
+
Rectangle.prototype.contains = function (other) {
|
|
108
|
+
return (this.left <= other.left && this.right >= other.right &&
|
|
109
|
+
this.top <= other.top && this.bottom >= other.bottom);
|
|
110
|
+
};
|
|
111
|
+
|
|
112
|
+
Rectangle.prototype.intersects = function (other) {
|
|
113
|
+
return (this.left <= other.right && this.right >= other.left &&
|
|
114
|
+
this.top <= other.bottom && this.bottom >= other.top);
|
|
115
|
+
};
|
|
116
|
+
|
|
117
|
+
Rectangle.prototype.overlaps = function (other) {
|
|
118
|
+
if (!this.intersects(other)) return null;
|
|
119
|
+
var oLeft = Math.max(this.left, other.left);
|
|
120
|
+
var oRight = Math.min(this.right, other.right);
|
|
121
|
+
var oTop = Math.max(this.top, other.top);
|
|
122
|
+
var oBottom = Math.min(this.bottom, other.bottom);
|
|
123
|
+
return new Rectangle(oLeft, oTop, oRight - oLeft, oBottom - oTop, null, false);
|
|
124
|
+
};
|
|
125
|
+
|
|
126
|
+
// ── Ejection (reposition other rect out of this rect) ────────────────
|
|
127
|
+
|
|
128
|
+
Rectangle.prototype.eject = function (other, toSide, contain) {
|
|
129
|
+
if (!this.overlaps(other)) return;
|
|
130
|
+
|
|
131
|
+
var newLeft = other.left;
|
|
132
|
+
var newTop = other.top;
|
|
133
|
+
|
|
134
|
+
switch (toSide) {
|
|
135
|
+
case 'top':
|
|
136
|
+
newTop = this.top - other.h - 1;
|
|
137
|
+
break;
|
|
138
|
+
case 'bottom':
|
|
139
|
+
newTop = this.bottom + 1;
|
|
140
|
+
break;
|
|
141
|
+
case 'left':
|
|
142
|
+
newLeft = this.left - other.w - 1;
|
|
143
|
+
break;
|
|
144
|
+
case 'right':
|
|
145
|
+
newLeft = this.right + 1;
|
|
146
|
+
break;
|
|
147
|
+
default:
|
|
148
|
+
// Closest side
|
|
149
|
+
var dLeft = Math.abs(this.left - other.left);
|
|
150
|
+
var dRight = Math.abs(this.right - other.left);
|
|
151
|
+
var dTop = Math.abs(this.top - other.top);
|
|
152
|
+
var dBottom = Math.abs(this.bottom - other.top);
|
|
153
|
+
var minD = Math.min(dLeft, dRight, dTop, dBottom);
|
|
154
|
+
if (minD === dLeft) {
|
|
155
|
+
newLeft = contain ? this.left + 1 : this.left - other.w - 1;
|
|
156
|
+
} else if (minD === dRight) {
|
|
157
|
+
newLeft = contain ? this.right - other.w - 1 : this.right + 1;
|
|
158
|
+
} else if (minD === dTop) {
|
|
159
|
+
newTop = contain ? this.top + 1 : this.top - other.h - 1;
|
|
160
|
+
} else {
|
|
161
|
+
newTop = contain ? this.bottom - other.h - 1 : this.bottom + 1;
|
|
162
|
+
}
|
|
163
|
+
}
|
|
164
|
+
other.top = newTop;
|
|
165
|
+
other.left = newLeft;
|
|
166
|
+
};
|
|
167
|
+
|
|
168
|
+
// ── Distance helpers ─────────────────────────────────────────────────
|
|
169
|
+
|
|
170
|
+
Rectangle.prototype.xDistanceFrom = function (point) {
|
|
171
|
+
return (this.left <= point.rect.x && point.rect.x <= this.right)
|
|
172
|
+
? 0
|
|
173
|
+
: Math.min(Math.abs(point.rect.x - this.left), Math.abs(point.rect.x - this.right));
|
|
174
|
+
};
|
|
175
|
+
|
|
176
|
+
Rectangle.prototype.yDistanceFrom = function (point) {
|
|
177
|
+
return (this.top <= point.rect.y && point.rect.y <= this.bottom)
|
|
178
|
+
? 0
|
|
179
|
+
: Math.min(Math.abs(point.rect.y - this.top), Math.abs(point.rect.y - this.bottom));
|
|
180
|
+
};
|
|
181
|
+
|
|
182
|
+
Rectangle.prototype.sqDistanceFrom = function (point) {
|
|
183
|
+
var dx = this.xDistanceFrom(point);
|
|
184
|
+
var dy = this.yDistanceFrom(point);
|
|
185
|
+
return dx * dx + dy * dy;
|
|
186
|
+
};
|
|
187
|
+
|
|
188
|
+
Rectangle.prototype.distanceFrom = function (point) {
|
|
189
|
+
return Math.sqrt(this.sqDistanceFrom(point));
|
|
190
|
+
};
|
|
191
|
+
|
|
192
|
+
Rectangle.prototype.toString = function () {
|
|
193
|
+
return 'Rectangle(x: ' + this._x + ', y: ' + this._y +
|
|
194
|
+
', w: ' + this.w + ', h: ' + this.h +
|
|
195
|
+
', left: ' + this._left + ', right: ' + this._right +
|
|
196
|
+
', top: ' + this._top + ', bottom: ' + this._bottom +
|
|
197
|
+
', is_centered: ' + this.is_centered + ')';
|
|
198
|
+
};
|
|
199
|
+
|
|
200
|
+
export { Rectangle };
|
|
@@ -0,0 +1,234 @@
|
|
|
1
|
+
/* Copyright 2023-2026 by Essam Abadir */
|
|
2
|
+
|
|
3
|
+
/**
|
|
4
|
+
* SlitLightSource — Engine-agnostic light source for the double-slit experiment.
|
|
5
|
+
* Creates a PointSource centered between the two slits of a SlitScreen.
|
|
6
|
+
*
|
|
7
|
+
* Engine-agnostic: works with both the JS reference engine and the Rust/WASM engine.
|
|
8
|
+
*/
|
|
9
|
+
|
|
10
|
+
import { PointSource } from './PointSource.js';
|
|
11
|
+
import { registerKind } from '../objects/kinds.js';
|
|
12
|
+
import { V1_REPLACEMENTS } from '../objects/v1-replacements.js';
|
|
13
|
+
|
|
14
|
+
// ── Imports (Node.js) or globals (browser) ──────────────────────────
|
|
15
|
+
|
|
16
|
+
// ── SlitLightSource ──────────────────────────────────────────────────
|
|
17
|
+
|
|
18
|
+
/**
|
|
19
|
+
* Radial point source positioned to illuminate both slits evenly.
|
|
20
|
+
*
|
|
21
|
+
* A thin wrapper around {@link PointSource} that positions the source
|
|
22
|
+
* automatically at the geometric center of the two slits: `x = 20`,
|
|
23
|
+
* `y = slit_wall_gap_top + slit_wall_gap_height / 2`. This equidistant
|
|
24
|
+
* placement ensures both slits receive identical particle flux, which is
|
|
25
|
+
* required for the interference fringes to be symmetric.
|
|
26
|
+
*
|
|
27
|
+
* ## Physics you can drive
|
|
28
|
+
*
|
|
29
|
+
* **`angle_increment`** (default 10 degrees) controls how many emission rays
|
|
30
|
+
* the source fires: `floor(360 / angle_increment)` rays. At 10° that is 36
|
|
31
|
+
* rays. The emission cone must reach both slits — the source is placed at
|
|
32
|
+
* x = 20 so rays at a wide range of angles hit the slit screen. Increasing
|
|
33
|
+
* `angle_increment` thins the ray count (coarser illumination); decreasing it
|
|
34
|
+
* increases ray density (smoother, more particle flux).
|
|
35
|
+
*
|
|
36
|
+
* **Emission radius** is hardcoded to `light_source_diameter / 2 = 8` px. Each
|
|
37
|
+
* ray's initial velocity is `vx = 8 * cos(θ)`, `vy = 8 * sin(θ)` (the
|
|
38
|
+
* `PointSource` emitter-registration pattern). The Universal Speed Limit caps
|
|
39
|
+
* actual movement to 1px/tick; excess becomes accumulated momentum.
|
|
40
|
+
*
|
|
41
|
+
* **Particle wavelength / mass:** the source passes `slitScreen.wavelength` to
|
|
42
|
+
* the inner `PointSource` as `opts.wavelength`, which sets each emitted
|
|
43
|
+
* particle's mass via `mass = capacity / wavelength`. This keeps particle mass
|
|
44
|
+
* consistent with the slit geometry scale.
|
|
45
|
+
*
|
|
46
|
+
* **`delay`** (default 1) sets ticks between bursts per angle. `delay = 0` fires
|
|
47
|
+
* every tick; `delay = 1` fires every other tick. Affects particle density but
|
|
48
|
+
* not fringe position.
|
|
49
|
+
*
|
|
50
|
+
* **`quantum_limit`** (default `Infinity`) caps total particles emitted per angle.
|
|
51
|
+
* Set a finite value to limit the total particle count (useful for single-shot
|
|
52
|
+
* or timed observations).
|
|
53
|
+
*
|
|
54
|
+
* @param {Object} universe - The engine universe instance (JS or WASM).
|
|
55
|
+
* @param {Object} slitScreen - A {@link SlitScreen} instance. Provides `slit_wall_gap_top`,
|
|
56
|
+
* `slit_wall_gap_height`, and `wavelength` for automatic positioning and mass.
|
|
57
|
+
* @param {number} [angle_increment=10] - Degrees between emission angles;
|
|
58
|
+
* `floor(360 / angle_increment)` total rays.
|
|
59
|
+
* @param {number} [quantum_limit=Infinity] - Max quanta emitted per angle before
|
|
60
|
+
* the emitter stops.
|
|
61
|
+
* @param {number} [delay=1] - Ticks between emission bursts per angle. 0 = every
|
|
62
|
+
* tick; 1 = every other tick.
|
|
63
|
+
* @param {Object} [opts] - WS-DSE-3D Bite B1.
|
|
64
|
+
* @param {number} [opts.depth] - When provided, threads `zMin=-depth/2,
|
|
65
|
+
* zDepth=depth` into the inner `PointSource`'s opts — the IDENTICAL shared
|
|
66
|
+
* z-spread mechanism WS-DSE-3D Bite B0 built for `setupWaveInterference`
|
|
67
|
+
* (`emitterProgram.js`'s opt-in `em.zMin`/`em.zDepth`). REUSE, not a fork —
|
|
68
|
+
* SlitLightSource is a thin PointSource wrapper (see module docstring), so
|
|
69
|
+
* this is the only line needed to make the DSE light source illuminate the
|
|
70
|
+
* full z-depth of the SLOT-shaped 3D slits (Bite B1's SlitScreen `depth`).
|
|
71
|
+
* OMITTED (default) → `zMin`/`zDepth` stay `undefined` on the PointSource
|
|
72
|
+
* opts object, which PointSource itself treats as `null` (byte-identical
|
|
73
|
+
* 2D behavior — zero extra `random()` draws, per `emitterProgram.js`).
|
|
74
|
+
*/
|
|
75
|
+
function SlitLightSource(universe, slitScreen, angle_increment, quantum_limit, delay, opts) {
|
|
76
|
+
angle_increment = (angle_increment !== undefined) ? angle_increment : 10;
|
|
77
|
+
quantum_limit = (quantum_limit !== undefined) ? quantum_limit : Infinity;
|
|
78
|
+
delay = (delay !== undefined) ? delay : 1;
|
|
79
|
+
opts = opts || {};
|
|
80
|
+
var depth = (opts.depth !== undefined && opts.depth !== null) ? opts.depth : null;
|
|
81
|
+
var zMin = (depth !== null) ? -depth / 2 : null;
|
|
82
|
+
var zDepth = (depth !== null) ? depth : null;
|
|
83
|
+
|
|
84
|
+
this.universe = universe;
|
|
85
|
+
this._schemaKind = 'SlitLightSource';
|
|
86
|
+
|
|
87
|
+
// Light source diameter: hardcoded to 16 matching devsdk's pointSOURCESIZE.
|
|
88
|
+
// (wavelength * 0.25 * 2 = 32 would double the emission radius and velocity)
|
|
89
|
+
var light_source_diameter = 16;
|
|
90
|
+
|
|
91
|
+
// Position: x=20, y=midpoint of inter-slit gap (equidistant from both slit centers).
|
|
92
|
+
// Previously used slit_wall_gap_top (top edge of gap), which biased toward slit1.
|
|
93
|
+
// Correct position = gap_top + gap_height/2 = slit pair center = canvas center.
|
|
94
|
+
var light_source_x = 20;
|
|
95
|
+
var light_source_center_y = slitScreen.slit_wall_gap_top + slitScreen.slit_wall_gap_height / 2;
|
|
96
|
+
|
|
97
|
+
var charge = null; // random +/- per particle
|
|
98
|
+
var speed = 1;
|
|
99
|
+
|
|
100
|
+
// LAB DRIVE FIX BATCH item 1 (2026-07-13, CEO): color OFF by default —
|
|
101
|
+
// this used to hardcode `color: [0, 255, 0]` (devsdk parity green),
|
|
102
|
+
// which OVERRIDES the render layer's colorScheme (LightColor ramp;
|
|
103
|
+
// "an explicit render.color OVERRIDES colorScheme, so ROYGBIV never
|
|
104
|
+
// shows on colored bodies" — docs/physics/COLOR_RENDER_LEARNINGS.md).
|
|
105
|
+
// That override made every double-slit-family page render a fixed green
|
|
106
|
+
// regardless of physics, while setupWaveInterference's PointSources
|
|
107
|
+
// pass NO color at all (colorless -> colorScheme-driven, genuine
|
|
108
|
+
// fullness/frequency-driven presentation) — the exact asymmetry the
|
|
109
|
+
// CEO flagged (WI shows real physics color; the Lab showed a flat
|
|
110
|
+
// override). `opts.color` is now an EXPLICIT opt-in (default `null` —
|
|
111
|
+
// colorless, PointSource's own `opts.color || null` already handles
|
|
112
|
+
// this correctly) so any caller that WANTS the old green back can
|
|
113
|
+
// still request it; none currently do (grepped: setupDoubleSlit.js,
|
|
114
|
+
// slit-family-depth.test.mjs, schema.test.mjs — zero callers pass
|
|
115
|
+
// `opts.color` to SlitLightSource, so this is a pure default flip).
|
|
116
|
+
var lightSourceColor = (opts.color !== undefined) ? opts.color : null;
|
|
117
|
+
|
|
118
|
+
// Create a PointSource (already engine-agnostic)
|
|
119
|
+
this.lightSource = new PointSource(
|
|
120
|
+
universe,
|
|
121
|
+
light_source_x,
|
|
122
|
+
light_source_center_y,
|
|
123
|
+
light_source_diameter,
|
|
124
|
+
speed,
|
|
125
|
+
charge,
|
|
126
|
+
true, // auto_fire
|
|
127
|
+
quantum_limit,
|
|
128
|
+
delay,
|
|
129
|
+
angle_increment,
|
|
130
|
+
{ color: lightSourceColor, wavelength: slitScreen.wavelength, zMin: zMin, zDepth: zDepth }
|
|
131
|
+
);
|
|
132
|
+
|
|
133
|
+
this.lightSource._owner = this; // THE ONE UP-LINK
|
|
134
|
+
}
|
|
135
|
+
|
|
136
|
+
/**
|
|
137
|
+
* Returns a tick function suitable for universe.experimentTickFunctions.
|
|
138
|
+
* Delegates to the PointSource's default tick function pattern:
|
|
139
|
+
* each emitter with auto_fire=true fires automatically via the engine.
|
|
140
|
+
* Returns a no-op since PointSource emitters auto-fire via the engine.
|
|
141
|
+
*/
|
|
142
|
+
SlitLightSource.prototype.getTickFunction = function () {
|
|
143
|
+
// PointSource emitters are registered with auto_fire=true,
|
|
144
|
+
// so the engine fires them in Phase A automatically.
|
|
145
|
+
// Return a no-op tick function for compatibility.
|
|
146
|
+
return function () {};
|
|
147
|
+
};
|
|
148
|
+
|
|
149
|
+
/**
|
|
150
|
+
* Enable/disable the light source.
|
|
151
|
+
* @param {boolean} active
|
|
152
|
+
*/
|
|
153
|
+
SlitLightSource.prototype.setActive = function (active) {
|
|
154
|
+
this.lightSource.setActive(active);
|
|
155
|
+
};
|
|
156
|
+
|
|
157
|
+
/**
|
|
158
|
+
* DSE LAB (2026-07-13): chargeMode passthrough — mirrors `setActive`'s delegation
|
|
159
|
+
* pattern. `PointSource.prototype.chargeMode`'s setter already covers
|
|
160
|
+
* `'random'|'positive'|'negative'|'both'` and is LIVE/read-per-emission with NO
|
|
161
|
+
* re-init (ground-truthed: it lazily registers whichever (charge,random_direction)
|
|
162
|
+
* handle groups the new mode needs, then flips `active` on the relevant groups —
|
|
163
|
+
* emitterProgram.js's tick-fn checks `em.active` fresh every tick, so the switch
|
|
164
|
+
* takes effect on the very next emission, not just future ones). The DSE Lab's
|
|
165
|
+
* `chargeMode` control (random|positive|negative) drives this directly —
|
|
166
|
+
* `slitLightSource.chargeMode = 'positive'` — reusing the IDENTICAL mechanism
|
|
167
|
+
* `setupWaveInterference`'s emitters would use, not a fork.
|
|
168
|
+
*/
|
|
169
|
+
Object.defineProperty(SlitLightSource.prototype, 'chargeMode', {
|
|
170
|
+
get: function () { return this.lightSource.chargeMode; },
|
|
171
|
+
set: function (mode) { this.lightSource.chargeMode = mode; },
|
|
172
|
+
enumerable: true,
|
|
173
|
+
configurable: true
|
|
174
|
+
});
|
|
175
|
+
|
|
176
|
+
// ── The kind (objects/kinds.js): descriptor, construction defaults, builder ──────────
|
|
177
|
+
|
|
178
|
+
/**
|
|
179
|
+
* SlitLightSource — Radial emitter positioned between slit pairs (wraps PointSource).
|
|
180
|
+
* Constructor: SlitLightSource(universe, slitScreen, angle_increment,
|
|
181
|
+
* quantum_limit, delay)
|
|
182
|
+
* Position is derived from slitScreen geometry at construction time.
|
|
183
|
+
* Group wrapper: the inner PointSource's per-angle handles are stamped with the ONE up-link `_owner` = <this>.
|
|
184
|
+
*/
|
|
185
|
+
var SlitLightSourceDescriptor = {
|
|
186
|
+
description: 'A radial light source for the double-slit experiment. ' +
|
|
187
|
+
'Wraps a PointSource positioned equidistant between the two slits ' +
|
|
188
|
+
'(at the inter-slit gap center), so particles reach both openings with equal path length. ' +
|
|
189
|
+
'Emits in all directions; the slit screen selects which particles pass through.',
|
|
190
|
+
fields: [
|
|
191
|
+
{
|
|
192
|
+
name: 'angle_increment',
|
|
193
|
+
type: 'number',
|
|
194
|
+
constraint: { min: 1, max: 360, integer: false },
|
|
195
|
+
engineVisible: true,
|
|
196
|
+
description: 'Degrees between emission angles (fewer degrees = more angles = denser wave front). 10° gives 36 directions, the double-slit experiment default.'
|
|
197
|
+
},
|
|
198
|
+
{
|
|
199
|
+
name: 'quantum_limit',
|
|
200
|
+
type: 'number',
|
|
201
|
+
constraint: { min: 1, integer: true },
|
|
202
|
+
engineVisible: true,
|
|
203
|
+
description: 'Max quanta per angle emitter (null/Infinity = unlimited). Limits total particle count for performance control.'
|
|
204
|
+
},
|
|
205
|
+
{
|
|
206
|
+
name: 'delay',
|
|
207
|
+
type: 'number',
|
|
208
|
+
constraint: { min: 0, integer: true },
|
|
209
|
+
engineVisible: true,
|
|
210
|
+
description: 'Ticks between bursts for each angle emitter. 1 = emit every other tick (default for the double-slit source).'
|
|
211
|
+
}
|
|
212
|
+
]
|
|
213
|
+
};
|
|
214
|
+
|
|
215
|
+
// ── SlitLightSource — cannot be built standalone ─────────────────────────
|
|
216
|
+
registerKind(SlitLightSource, {
|
|
217
|
+
from: import.meta.url,
|
|
218
|
+
descriptor: SlitLightSourceDescriptor,
|
|
219
|
+
defaults: {
|
|
220
|
+
angle_increment: 10,
|
|
221
|
+
quantum_limit: null,
|
|
222
|
+
delay: 1
|
|
223
|
+
},
|
|
224
|
+
build: function () {
|
|
225
|
+
throw new Error('[ObjectFactory] create("SlitLightSource"): a SlitLightSource requires a paired ' +
|
|
226
|
+
'SlitScreen and cannot be constructed independently — build it through its setup factory ' +
|
|
227
|
+
'(setupDoubleSlit), or compose ' + V1_REPLACEMENTS.SlitLightSource + '. (FAIL-LOUD.)');
|
|
228
|
+
}
|
|
229
|
+
});
|
|
230
|
+
|
|
231
|
+
// ── Export ───────────────────────────────────────────────────────────
|
|
232
|
+
|
|
233
|
+
export { SlitLightSource };
|
|
234
|
+
|