Skip to content

Commit 8d78c5d

Browse files
committed
draw curve from radio button
1 parent 282fa32 commit 8d78c5d

File tree

2 files changed

+45
-14
lines changed

2 files changed

+45
-14
lines changed

apps/website/src/components/Polar/Polar.tsx

Lines changed: 31 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -1,5 +1,5 @@
11
import { assert } from '@cutting/assert';
2-
import { Box } from '@cutting/component-library';
2+
import { Box, RadioGroup } from '@cutting/component-library';
33
import { ResponsiveSVG } from '@cutting/svg';
44
import { useParentSize } from '@cutting/use-get-parent-size';
55
import { MathJax } from '@cutting/use-mathjax';
@@ -9,11 +9,12 @@ import { scaleLinear } from '@visx/scale';
99
import { LinePath } from '@visx/shape';
1010
import { extent } from 'd3-array';
1111
import { parse } from 'mathjs';
12-
import { useLayoutEffect, useMemo, useReducer, useRef } from 'react';
12+
import { useLayoutEffect, useMemo, useReducer, useRef, useState } from 'react';
1313

1414
import { ApplicationLayout } from '~/layouts/ApplicationLayout';
1515

1616
import * as styles from './Polar.css';
17+
import type { PolarEffect } from './reducer';
1718
import { initialState, reducer } from './reducer';
1819

1920
export function Polar(): JSX.Element {
@@ -23,6 +24,7 @@ export function Polar(): JSX.Element {
2324
initialValues: { width: 0, height: 0 },
2425
});
2526
const tickFrame = useRef<number>(undefined);
27+
const [polarEffect, setPolarEffect] = useState<PolarEffect>('butterfly');
2628

2729
const [state, dispatch] = useReducer(reducer, initialState);
2830

@@ -49,8 +51,9 @@ export function Polar(): JSX.Element {
4951
}, [state.bucket, width, height]);
5052

5153
useLayoutEffect(() => {
52-
dispatch({ type: 'SET_EXPRESSION', payload: { expression: state.expression } });
53-
}, [state.expression]);
54+
dispatch({ type: 'SET_POLAR_EFFECT', payload: { polarEffect } });
55+
}, [polarEffect, state.expression]);
56+
5457
useLayoutEffect(() => {
5558
if (state.time === 0) {
5659
return;
@@ -75,9 +78,31 @@ export function Polar(): JSX.Element {
7578
}
7679

7780
return (
78-
<ApplicationLayout heading="The Polar Express!" showFooter={false}>
81+
<ApplicationLayout heading="The Polar Express" showFooter={false}>
7982
<section ref={containerRef} className={styles.container}>
80-
<Box display="flex" justifyContent="center">
83+
<Box display="flex" justifyContent={{ mobile: 'flexStart', tablet: 'spaceBetween' }}>
84+
<RadioGroup<PolarEffect>
85+
legend="Trigonometric Function"
86+
legendMode="screen-reader-only"
87+
name="theme"
88+
checkableLayout="inline"
89+
checkableSize={'large'}
90+
onChange={(o) => {
91+
setPolarEffect(o.target.value as PolarEffect);
92+
}}
93+
options={[
94+
{
95+
value: 'butterfly',
96+
content: 'Butterfly',
97+
checked: polarEffect === 'butterfly',
98+
},
99+
{
100+
value: 'rose',
101+
content: 'Rose',
102+
checked: polarEffect === 'rose',
103+
},
104+
]}
105+
/>
81106
<MathJax className={styles.expression}>{`$ r = ${parse(state.expression).toTex()}$`}</MathJax>
82107
</Box>
83108
<ResponsiveSVG width={width} height={height} overflow="hidden" className="polar-svg">

apps/website/src/components/Polar/reducer.ts

Lines changed: 14 additions & 8 deletions
Original file line numberDiff line numberDiff line change
@@ -4,19 +4,27 @@ import { parse } from 'mathjs';
44
import type { Reducer } from 'react';
55
import { match } from 'ts-pattern';
66

7+
const polarEffects = {
8+
['butterfly']: 'e^(sin(x)) - 2 * cos(4x) + (sin((2x - pi) / 24))^5',
9+
['rose']: 'sin(4x)',
10+
} as const;
11+
12+
export type PolarEffect = keyof typeof polarEffects;
13+
714
type State = {
815
expression: string;
916
points: Point[];
1017
current: Point[];
1118
bucket: Point[];
1219
time: number;
20+
polarEffect: PolarEffect;
1321
};
1422

1523
type PolarActions =
1624
| {
17-
type: 'SET_EXPRESSION';
25+
type: 'SET_POLAR_EFFECT';
1826
payload: {
19-
expression: string;
27+
polarEffect: PolarEffect;
2028
};
2129
}
2230
| {
@@ -45,9 +53,6 @@ function getPolarCurvePointsFromParsed(
4553
return points;
4654
}
4755

48-
// butterfly curve e^(sin(x)) - 2 * cos(4x) + (sin((2x - pi) / 24))^5
49-
// rose curve sin(4x)
50-
5156
export const initialState: State = {
5257
expression: 'e^(sin(x)) - 2 * cos(4x) + (sin((2x - pi) / 24))^5',
5358
points: [],
@@ -58,15 +63,16 @@ export const initialState: State = {
5863

5964
export const reducer: Reducer<State, PolarActions> = produce((state, action) => {
6065
return match(action)
61-
.with({ type: 'SET_EXPRESSION' }, ({ payload }) => {
62-
const node = parse(payload.expression);
66+
.with({ type: 'SET_POLAR_EFFECT' }, ({ payload }) => {
67+
const expression = polarEffects[payload.polarEffect];
68+
const node = parse(expression);
6369
const compiledFn = node.compile();
6470
state.current = [];
6571
const points = getPolarCurvePointsFromParsed(compiledFn, 0, 2 * Math.PI, 100);
6672

6773
state.bucket = points;
6874
state.points = [...points];
69-
state.expression = payload.expression;
75+
state.expression = expression;
7076
state.time = 1;
7177
})
7278
.with({ type: 'TICK' }, () => {

0 commit comments

Comments
 (0)