export interface Point { x: number; y: number; z: number } export interface Charge extends Point { coulombs: number } export const COULOMB_CONSTANT = 8.9875517923e9; /** SI units: positions in metres, charges in coulombs, output in N/C. * Samples inside 0.18 m of a charge are omitted to avoid visual singularities. */ export function electricField(point: Point, charges: readonly Charge[]): Point { const field = { x: 0, y: 0, z: 0 }; for (const charge of charges) { const dx = point.x - charge.x; const dy = point.y - charge.y; const dz = point.z - charge.z; const r2 = dx * dx + dy * dy + dz * dz; if (r2 < 0.18 ** 2) continue; const factor = COULOMB_CONSTANT * charge.coulombs / (r2 * Math.sqrt(r2)); field.x += factor * dx; field.y += factor * dy; field.z += factor * dz; } return field; }