import { useState } from 'react' import type { FuncName, NodeKind } from '../engine/types.ts' export interface Settings { f: FuncName fexpr: string a: number b: number n: number d: number nodes: NodeKind seed: number } const FUNCS: { id: FuncName; label: string; hint: string }[] = [ { id: 'runge', label: '1 / (1 + x²)', hint: "Runge's example, the paper's Figure 1" }, { id: 'sine', label: 'sin x', hint: 'Figure 2, smooth everywhere' }, { id: 'abs', label: '|x|', hint: 'Figure 3, a corner at 0' }, { id: 'custom', label: 'custom', hint: 'any MATLAB expression in x' }, ] const NODES: { id: NodeKind; label: string; hint: string }[] = [ { id: 'uniform', label: 'uniform', hint: 'equally spaced, as in every figure of the paper' }, { id: 'chebyshev', label: 'Chebyshev', hint: 'clustered at both ends' }, { id: 'random', label: 'random', hint: 'sorted uniform draws, endpoints kept' }, { id: 'paired', label: 'paired', hint: 'every second node pulled close to its neighbour' }, { id: 'graded', label: 'graded', hint: 'quadratically clustered at the left end' }, ] interface Props { value: Settings onChange: (patch: Partial) => void /** the convergence tab sets n itself */ showN: boolean busy: boolean } export default function Controls({ value: v, onChange, showN, busy }: Props) { const [more, setMore] = useState(false) const dMax = Math.min(v.n, 12) return (
function f
{FUNCS.map((fn) => ( ))}
{v.f === 'custom' && (
f(x) = onChange({ fexpr: e.target.value })} />
)} {showN && (
nodes n = {v.n} { const n = Number(e.target.value) onChange({ n, d: Math.min(v.d, Math.min(n, 12)) }) }} />
)}
blend degree d = {v.d} onChange({ d: Number(e.target.value) })} />
node distribution
{NODES.map((nd) => ( ))} {v.nodes === 'random' && ( )}
{more && (
interval
{ const a = Number(e.target.value) if (isFinite(a) && a < v.b) onChange({ a }) }} /> to { const b = Number(e.target.value) if (isFinite(b) && b > v.a) onChange({ b }) }} />
)}
) }