Skip to content

Commit 25f12ab

Browse files
committed
delay icon: dashed input + delayed output sine pair
1 parent 3abac8d commit 25f12ab

4 files changed

Lines changed: 39 additions & 2 deletions

File tree

src/lib/components/icons/BlockIcon.svelte

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -40,6 +40,7 @@
4040
{#if def.kind === 'plot'}
4141
<IconPlot
4242
samples={def.samples()}
43+
samplesDashed={def.samplesDashed?.()}
4344
xRange={def.xRange}
4445
yRange={def.yRange}
4546
axes={def.axes}

src/lib/components/icons/blocks/IconPlot.svelte

Lines changed: 10 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -6,6 +6,7 @@
66
77
interface Props {
88
samples: Sample[];
9+
samplesDashed?: Sample[];
910
xRange?: [number, number];
1011
yRange?: [number, number];
1112
axes?: AxesMode;
@@ -15,6 +16,7 @@
1516
1617
let {
1718
samples,
19+
samplesDashed,
1820
xRange = [0, 1],
1921
yRange = [0, 1],
2022
axes = 'cross',
@@ -23,6 +25,11 @@
2325
}: Props = $props();
2426
2527
const path = $derived(buildPath(samples, xRange[0], xRange[1], yRange[0], yRange[1]));
28+
const pathDashed = $derived(
29+
samplesDashed
30+
? buildPath(samplesDashed, xRange[0], xRange[1], yRange[0], yRange[1])
31+
: ''
32+
);
2633
2734
const xAxisY = $derived(
2835
yRange[0] <= 0 && yRange[1] >= 0 ? mapY(0, yRange[0], yRange[1]) : AXIS_BOX.y1
@@ -42,6 +49,9 @@
4249
{#if axes === 'cross'}
4350
<line x1={yAxisX} y1={AXIS_BOX.y0} x2={yAxisX} y2={AXIS_BOX.y1} />
4451
{/if}
52+
{#if pathDashed}
53+
<path d={pathDashed} stroke-dasharray="3 2.5" />
54+
{/if}
4555
<path d={path} />
4656
{#if markers}
4757
{#each finiteSamples as [x, v]}

src/lib/components/icons/blocks/curves.ts

Lines changed: 21 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -287,6 +287,27 @@ export function delaySamples(t1 = 0.15, tau = 0.3): Sample[] {
287287
];
288288
}
289289

290+
/** Input sine for the Delay icon — runs over the full window, one full cycle. */
291+
export function delayInputSineSamples(cycles = 1, n = 64): Sample[] {
292+
const out: Sample[] = [];
293+
for (let i = 0; i < n; i++) {
294+
const t = i / (n - 1);
295+
out.push([t, Math.sin(2 * Math.PI * cycles * t)]);
296+
}
297+
return out;
298+
}
299+
300+
/** Output sine for the Delay icon — flat at 0 until t1, then the same sine
301+
* shifted by t1 (so it tracks the input one delay later). */
302+
export function delayOutputSineSamples(t1 = 0.25, cycles = 1, n = 56): Sample[] {
303+
const out: Sample[] = [[0, 0], [t1, 0]];
304+
for (let i = 1; i < n; i++) {
305+
const t = t1 + (1 - t1) * (i / (n - 1));
306+
out.push([t, Math.sin(2 * Math.PI * cycles * (t - t1))]);
307+
}
308+
return out;
309+
}
310+
290311
/** Differentiator step response: a sharp impulse at the step instant */
291312
export function impulseSamples(t0 = 0.45, width = 0.04): Sample[] {
292313
return [

src/lib/components/icons/blocks/registry.ts

Lines changed: 7 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -15,7 +15,7 @@ import * as C from './curves';
1515
type AxesMode = 'none' | 'baseline' | 'cross';
1616

1717
export type IconDef =
18-
| { kind: 'plot'; samples: () => Sample[]; xRange?: [number, number]; yRange?: [number, number]; axes?: AxesMode; markers?: boolean; decoration?: 'arrow-up' | 'arrow-down' }
18+
| { kind: 'plot'; samples: () => Sample[]; samplesDashed?: () => Sample[]; xRange?: [number, number]; yRange?: [number, number]; axes?: AxesMode; markers?: boolean; decoration?: 'arrow-up' | 'arrow-down' }
1919
| { kind: 'scope'; samples: () => Sample[]; samples2?: () => Sample[]; yRange?: [number, number]; gridX?: number; gridY?: number }
2020
| { kind: 'surface'; fn?: (u: number, v: number) => number; rows?: number; cols?: number }
2121
| { kind: 'math'; latex: string }
@@ -52,7 +52,12 @@ export const iconRegistry: Record<string, IconDef> = {
5252
LeadLag: { kind: 'plot', samples: () => C.leadLagStepSamples(), yRange: LEADLAG_RANGE },
5353
Integrator: { kind: 'plot', samples: () => C.rampSamples() },
5454
Differentiator: { kind: 'plot', samples: () => C.differentiatorBode() },
55-
Delay: { kind: 'plot', samples: () => C.delaySamples() },
55+
Delay: {
56+
kind: 'plot',
57+
samples: () => C.delayOutputSineSamples(),
58+
samplesDashed: () => C.delayInputSineSamples(),
59+
yRange: Y_BIPOLAR
60+
},
5661
PID: { kind: 'plot', samples: () => C.pidStepSamples(), yRange: PT2_RANGE },
5762
AntiWindupPID: { kind: 'plot', samples: () => C.pt1StepSamples(0.12, 0.12) },
5863

0 commit comments

Comments
 (0)