aboutsummaryrefslogtreecommitdiff
path: root/src/experiments.ts
diff options
context:
space:
mode:
authorLalleSX2026-10-24 14:58:21 +0200
committerLalleSX2026-10-24 14:58:21 +0200
commit73b09270c54acab810c10a80bed1d77c1a7bb2ab (patch)
treee5bae1180c9a76345cc7779a24988875542d2dd9 /src/experiments.ts
parentAdd tests for math rendering and interactive scenes; update navigation and viewport handling (diff)
download3D-Electrophysics-main.tar.gz
3D-Electrophysics-main.zip
Tilføj danskHEADmain
Diffstat (limited to 'src/experiments.ts')
-rw-r--r--src/experiments.ts15
1 files changed, 12 insertions, 3 deletions
diff --git a/src/experiments.ts b/src/experiments.ts
index 6045a88..d4d2bc2 100644
--- a/src/experiments.ts
+++ b/src/experiments.ts
@@ -1,3 +1,4 @@
+import { getLanguage, word } from './i18n';
import { electricField, type Charge } from './physics/electricField';
import { capacitor, conductor, forceOn, gaussianFlux, pairEnergy, potential, semiconductor } from './physics/models';
@@ -31,7 +32,15 @@ export function format(value: number, digits = 2): string {
if (Math.abs(value) < 0.01 || Math.abs(value) >= 1e5) return value.toExponential(2);
return value.toLocaleString('en', { maximumFractionDigits: digits });
}
-const metric = (label: string, value: number, unit: string): Measurement => ({ label, value: format(value), unit });
+export function formatDisplay(value: number, digits = 2): string {
+ if (getLanguage() !== 'da') return format(value, digits);
+ if (!Number.isFinite(value)) return 'Udefineret';
+ if (value === 0) return '0';
+ const locale = 'da-DK';
+ if (Math.abs(value) < 0.01 || Math.abs(value) >= 1e5) return value.toLocaleString(locale, { notation: 'scientific', maximumFractionDigits: 2 });
+ return value.toLocaleString(locale, { maximumFractionDigits: digits });
+}
+const metric = (label: string, value: number, unit: string): Measurement => ({ label, value: formatDisplay(value), unit });
const textbook = (page: string) => ({ title: 'OpenStax · University Physics', url: `https://openstax.org/books/university-physics-volume-2/pages/${page}` });
export function chargePair(p: Parameters): Charge[] {
const half = number(p, 'separation') / 2;
@@ -68,7 +77,7 @@ export const experiments: Experiment[] = [
const charges = chargePair(p);
const e = electricField({ x: 0, y: 0, z: 0 }, charges);
const f = forceOn(charges[1], [charges[0]]);
- return [metric('|E| at origin', Math.hypot(e.x, e.y, e.z), 'N/C'), metric('|Force on right charge|', Math.hypot(f.x, f.y, f.z) * 1e9, 'nN'), { label: 'Interaction', value: p.configuration === 'like' ? 'Repulsive' : 'Attractive', unit: '' }];
+ return [metric('|E| at origin', Math.hypot(e.x, e.y, e.z), 'N/C'), metric('|Force on right charge|', Math.hypot(f.x, f.y, f.z) * 1e9, 'nN'), { label: 'Interaction', value: word(p.configuration === 'like' ? 'Repulsive' : 'Attractive'), unit: '' }];
},
},
{
@@ -85,7 +94,7 @@ export const experiments: Experiment[] = [
measure: p => {
const q = { x: number(p, 'position'), y: 0, z: 0, coulombs: number(p, 'charge') * 1e-9 };
const flux = gaussianFlux([q], number(p, 'radius'));
- return [metric('Net electric flux', flux, 'N·m²/C'), metric('Enclosed charge', Number.isNaN(flux) ? NaN : Math.abs(q.x) < number(p, 'radius') ? q.coulombs * 1e9 : 0, 'nC'), { label: 'Source location', value: Number.isNaN(flux) ? 'On surface' : Math.abs(q.x) < number(p, 'radius') ? 'Inside' : 'Outside', unit: '' }];
+ return [metric('Net electric flux', flux, 'N·m²/C'), metric('Enclosed charge', Number.isNaN(flux) ? NaN : Math.abs(q.x) < number(p, 'radius') ? q.coulombs * 1e9 : 0, 'nC'), { label: 'Source location', value: word(Number.isNaN(flux) ? 'On surface' : Math.abs(q.x) < number(p, 'radius') ? 'Inside' : 'Outside'), unit: '' }];
},
},
{