aboutsummaryrefslogtreecommitdiff
path: root/README.md
blob: ce86f3a03f456e420f757fbaf9a5f9ab7efd698d (plain) (blame)
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
# Fieldwork ยท Electrophysics

An interactive 3D learning lab built with TypeScript, Vite, Three.js, and KaTeX.
`PLAN.md` controls the subject scope. The only implemented subject is **Electric flux and charge**.

## Run locally

Use Node 22 (at least 22.12.0), as specified in `.nvmrc`.

```sh
npm install
npm run dev
```

Open the local URL printed by Vite. `npm run build` type-checks and builds the app into `dist/`; `npm run preview` serves that build. `npm run typecheck` runs TypeScript separately.

No test scripts or test files were created for this implementation. The pre-existing test commands and dependencies in `package.json` are retained, but there is no test suite in the current working tree.

## The experiment

- Change a point charge from โˆ’5 to +5 nC and move it along the x-axis.
- Choose a sphere or cube and change its radius or half side length.
- Compare enclosed charge, surface area, and exact net flux.
- Try positive, negative, and external-charge presets.
- Toggle the surface, field lines, and outward normals.
- Drag to orbit; scroll to zoom. Focus the canvas and use arrow keys to orbit, `+`/`โˆ’` to zoom, and `Home` to reset. All other controls are native keyboard-operable inputs.

The model assumes a stationary ideal point charge in vacuum. The imaginary Gaussian surface is centered at the origin. Geometry uses metres, physics uses SI units, and the interface presents charge in nanocoulombs. A nonzero charge exactly on the surface produces an undefined enclosed-charge/flux result because its field is singular there. The visible marker's radius does not change the point-charge model. Sampled lines and fixed-size arrows illustrate field direction; total flux is calculated analytically, never by counting those lines.

Reference: `docs/theory/3Electric flux and charge.pdf`, sections 3.2โ€“3.4. Lesson copy and graphics are original, based on these definitions.

## Add another 3D model

1. Enable its subject in `PLAN.md` first.
2. Create `src/models/<model-id>/` with separate physics, state, scene, and view modules.
3. Implement `ModelDefinition` from `src/core/model.ts`. `mount(host, { i18n })` renders into its host and returns a `ModelInstance` whose `dispose()` releases listeners, GPU resources, and observers.
4. Add its title, controls, explanations, accessibility text, and messages to `src/i18n/en.ts`.
5. Register a lazy-loading definition in `src/models/registry.ts`. The current shell mounts its first entry. Add model selection to the shell when a second enabled model is implemented; each model's physics and scene remain independent.

`src/models/electric-flux/physics.ts` has no dependency on DOM, Three.js, or translations. Rendering consumes physical field directions; it does not own the equations or measurement state. Scenes render only when controls, state, or viewport size changes.

## Add a language

English (`en`) is the default and fallback. User-facing copy is in `src/i18n/en.ts`, accessed through stable typed keys. Messages accept named parameters and numbers use `Intl.NumberFormat`.

To support another language, add its catalog and register its BCP 47 locale in `src/i18n/index.ts`. Pass that locale to `createI18n` in the shell. Missing messages fall back to English. No physics or model components need rewriting. Add a language selector only once another language has been requested and supplied.

## Layout

```text
src/core/                    Shared model lifecycle contract
src/i18n/                    English catalog, locale registry, formatting
src/models/registry.ts       Enabled, lazy-loaded models
src/models/electric-flux/    Pure physics, state, Three.js scene, lesson view
src/ui/                      Shared interface graphics
src/main.ts                  Application shell
src/style.css                Responsive presentation
```