diff --git a/blog/2024-11-15-playing-with-fire/1-introduction/GasketWeighted.tsx b/blog/2024-11-15-playing-with-fire/1-introduction/GasketWeighted.tsx index d2edb62..c3f91f1 100644 --- a/blog/2024-11-15-playing-with-fire/1-introduction/GasketWeighted.tsx +++ b/blog/2024-11-15-playing-with-fire/1-introduction/GasketWeighted.tsx @@ -28,8 +28,8 @@ export default function GasketWeighted() { const weightInput = (title, weight, setWeight) => ( <> -
-

{title} weight:{weight}

+
+

{title} weight: {weight}

setWeight(Number(e.currentTarget.value))}/>
@@ -38,7 +38,7 @@ export default function GasketWeighted() { return ( <> -
+
{weightInput("F_0", f0Weight, setF0Weight)} {weightInput("F_1", f1Weight, setF1Weight)} {weightInput("F_2", f2Weight, setF2Weight)} diff --git a/blog/2024-11-15-playing-with-fire/2-transforms/CoefEditor.tsx b/blog/2024-11-15-playing-with-fire/2-transforms/CoefEditor.tsx new file mode 100644 index 0000000..8536381 --- /dev/null +++ b/blog/2024-11-15-playing-with-fire/2-transforms/CoefEditor.tsx @@ -0,0 +1,48 @@ +import TeX from "@matejmazur/react-katex"; +import {Coefs} from "../src/coefs"; + +import styles from "../src/css/styles.module.css"; + +export interface Props { + title: String; + isPost: boolean; + coefs: Coefs; + setCoefs: (coefs: Coefs) => void; +} +export const CoefEditor = ({title, isPost, coefs, setCoefs}: Props) => { + return ( +
+

{title}

+
+

{isPost ? \alpha : 'a'}: {coefs.a}

+ setCoefs({...coefs, a: Number(e.currentTarget.value)})}/> +
+
+

{isPost ? \beta : 'b'}: {coefs.b}

+ setCoefs({...coefs, b: Number(e.currentTarget.value)})}/> +
+
+

{isPost ? \gamma : 'c'}: {coefs.c}

+ setCoefs({...coefs, c: Number(e.currentTarget.value)})}/> +
+
+

{isPost ? \delta : 'd'}: {coefs.d}

+ setCoefs({...coefs, d: Number(e.currentTarget.value)})}/> +
+
+

{isPost ? \epsilon : 'e'}: {coefs.e}

+ setCoefs({...coefs, e: Number(e.currentTarget.value)})}/> +
+
+

{isPost ? \zeta : 'f'}: {coefs.f}

+ setCoefs({...coefs, f: Number(e.currentTarget.value)})}/> +
+
+ ) +} \ No newline at end of file diff --git a/blog/2024-11-15-playing-with-fire/2-transforms/FlameBlend.tsx b/blog/2024-11-15-playing-with-fire/2-transforms/FlameBlend.tsx index 5ef84c7..b54db96 100644 --- a/blog/2024-11-15-playing-with-fire/2-transforms/FlameBlend.tsx +++ b/blog/2024-11-15-playing-with-fire/2-transforms/FlameBlend.tsx @@ -1,15 +1,7 @@ import {useContext, useEffect, useState} from "react"; -import { blend } from "./blend"; -import { applyCoefs, Coefs } from "../src/coefs" -import {randomBiUnit} from "../src/randomBiUnit"; -import {linear} from "../src/linear"; -import {julia} from "../src/julia"; -import {popcorn} from "../src/popcorn"; -import {pdj} from "../src/pdj"; -import {Variation} from "../src/variation"; import {Transform} from "../src/transform"; import { - pdjParams, + identityCoefs, xform1Coefs, xform1Weight, xform2Coefs, @@ -17,26 +9,15 @@ import { xform3Coefs, xform3Weight } from "../src/params"; -import {randomChoice} from "../src/randomChoice"; -import {plotBinary} from "../src/plotBinary" import {PainterContext} from "../src/Canvas" - -import styles from "../src/css/styles.module.css" - -type VariationBlend = { - linear: number, - julia: number, - popcorn: number, - pdj: number -} +import {buildBlend, buildTransform} from "./buildTransform" +import {chaosGameFinal} from "./chaosGameFinal" +import {VariationEditor, VariationProps} from "./VariationEditor" export default function FlameBlend() { - const quality = 2; - const step = 5000; - const {width, height, setPainter} = useContext(PainterContext); - const xform1Default: VariationBlend = { + const xform1Default: VariationProps = { linear: 0, julia: 1, popcorn: 0, @@ -44,7 +25,7 @@ export default function FlameBlend() { } const [xform1Variations, setXform1Variations] = useState(xform1Default) - const xform2Default: VariationBlend = { + const xform2Default: VariationProps = { linear: 1, julia: 0, popcorn: 1, @@ -52,7 +33,7 @@ export default function FlameBlend() { } const [xform2Variations, setXform2Variations] = useState(xform2Default) - const xform3Default: VariationBlend = { + const xform3Default: VariationProps = { linear: 0, julia: 0, popcorn: 0, @@ -60,80 +41,21 @@ export default function FlameBlend() { } const [xform3Variations, setXform3Variations] = useState(xform3Default) - function buildTransform(coefs: Coefs, variations: VariationBlend): Transform { - return (x: number, y: number) => { - const [varX, varY] = applyCoefs(x, y, coefs); - const varFunctions: [number, Variation][] = [ - [variations.linear, linear], - [variations.julia, julia], - [variations.popcorn, popcorn(coefs)], - [variations.pdj, pdj(pdjParams)] - ] + // Cheating a bit here; for purposes of code re-use, use the post- and final-transform-enabled chaos game, + // and swap in identity components for each + const identityXform: Transform = (x, y) => [x, y]; - return blend(varX, varY, varFunctions); - } - } - - const image = new ImageData(width, height); - function* chaosGame() { - let [x, y] = [randomBiUnit(), randomBiUnit()]; - const transforms: [number, Transform][] = [ - [xform1Weight, buildTransform(xform1Coefs, xform1Variations)], - [xform2Weight, buildTransform(xform2Coefs, xform2Variations)], - [xform3Weight, buildTransform(xform3Coefs, xform3Variations)] - ] - - const iterations = quality * image.width * image.height; - for (let i = 0; i < iterations; i++) { - let [_, transform] = randomChoice(transforms); - [x, y] = transform(x, y); - - if (i > 20) - plotBinary(x, y, image); - - if (i % step === 0) { - console.log(`Checking in; iterations=${i}`) - yield image; - } - } - - yield image; - } - useEffect(() => setPainter(chaosGame()), [xform1Variations, xform2Variations, xform3Variations]); - - const variationEditor = (title, variations, setVariations) => { - return ( - <> -

{title}:

-
-

Linear: {variations.linear}

- setVariations({...variations, linear: Number(e.currentTarget.value)})}/> -
-
-

Julia: {variations.julia}

- setVariations({...variations, julia: Number(e.currentTarget.value)})}/> -
-
-

Popcorn: {variations.popcorn}

- setVariations({...variations, popcorn: Number(e.currentTarget.value)})}/> -
-
-

PDJ: {variations.pdj}

- setVariations({...variations, pdj: Number(e.currentTarget.value)})}/> -
- - ) - } + useEffect(() => setPainter(chaosGameFinal(width, height, [ + [xform1Weight, buildTransform(xform1Coefs, buildBlend(xform1Coefs, xform1Variations))], + [xform2Weight, buildTransform(xform2Coefs, buildBlend(xform2Coefs, xform2Variations))], + [xform3Weight, buildTransform(xform3Coefs, buildBlend(xform3Coefs, xform3Variations))] + ], identityXform)), [xform1Variations, xform2Variations, xform3Variations]); return ( -
- {variationEditor("Transform 1", xform1Variations, setXform1Variations)} - {variationEditor("Transform 2", xform2Variations, setXform2Variations)} - {variationEditor("Transform 3", xform3Variations, setXform3Variations)} -
+ <> + + + + ) } \ No newline at end of file diff --git a/blog/2024-11-15-playing-with-fire/2-transforms/FlameFinal.tsx b/blog/2024-11-15-playing-with-fire/2-transforms/FlameFinal.tsx new file mode 100644 index 0000000..ade4637 --- /dev/null +++ b/blog/2024-11-15-playing-with-fire/2-transforms/FlameFinal.tsx @@ -0,0 +1,64 @@ +import {useContext, useEffect, useState} from "react"; +import {Coefs} from "../src/coefs" +import { + xform1Coefs, + xform1Weight, + xform1Variations, + xform1CoefsPost, + xform2Coefs, + xform2Weight, + xform2Variations, + xform2CoefsPost, + xform3Coefs, + xform3Weight, + xform3Variations, + xform3CoefsPost, + xformFinalCoefs as xformFinalCoefsDefault, + xformFinalCoefsPost as xformFinalCoefsPostDefault, +} from "../src/params"; +import {PainterContext} from "../src/Canvas" +import {buildBlend, buildTransform} from "./buildTransform"; +import {transformPost} from "./post"; +import {chaosGameFinal} from "./chaosGameFinal" +import {VariationEditor, VariationProps} from "./VariationEditor"; +import {CoefEditor} from "./CoefEditor"; +import {Transform} from "../src/transform"; + +export default function FlameFinal() { + const {width, height, setPainter} = useContext(PainterContext); + + const [xformFinalCoefs, setXformFinalCoefs] = useState(xformFinalCoefsDefault); + + const xformFinalVariationsDefault: VariationProps = { + linear: 0, + julia: 1, + popcorn: 0, + pdj: 0 + } + const [xformFinalVariations, setXformFinalVariations] = useState(xformFinalVariationsDefault); + + const [xformFinalCoefsPost, setXformFinalCoefsPost] = useState(xformFinalCoefsPostDefault); + + useEffect(() => { + const transforms: [number, Transform][] = [ + [xform1Weight, transformPost(buildTransform(xform1Coefs, xform1Variations), xform1CoefsPost)], + [xform2Weight, transformPost(buildTransform(xform2Coefs, xform2Variations), xform2CoefsPost)], + [xform3Weight, transformPost(buildTransform(xform3Coefs, xform3Variations), xform3CoefsPost)] + ]; + + const finalBlend = buildBlend(xformFinalCoefs, xformFinalVariations); + const finalTransform = buildTransform(xformFinalCoefs, finalBlend); + const finalPost = transformPost(finalTransform, xformFinalCoefsPost); + + setPainter(chaosGameFinal(width, height, transforms, finalPost)); + }, [xformFinalCoefs, xformFinalVariations, xformFinalCoefsPost]); + + return ( + <> + + + + + ) +} \ No newline at end of file diff --git a/blog/2024-11-15-playing-with-fire/2-transforms/FlamePost.tsx b/blog/2024-11-15-playing-with-fire/2-transforms/FlamePost.tsx new file mode 100644 index 0000000..9b5a6a4 --- /dev/null +++ b/blog/2024-11-15-playing-with-fire/2-transforms/FlamePost.tsx @@ -0,0 +1,46 @@ +import {useContext, useEffect, useState} from "react"; +import {Coefs} from "../src/coefs" +import {Transform} from "../src/transform"; +import { + xform1Coefs, + xform1Weight, + xform1Variations, + xform1CoefsPost as xform1CoefsPostDefault, + xform2Coefs, + xform2Weight, + xform2Variations, + xform2CoefsPost as xform2CoefsPostDefault, + xform3Coefs, + xform3Weight, + xform3Variations, + xform3CoefsPost as xform3CoefsPostDefault +} from "../src/params"; +import {PainterContext} from "../src/Canvas" +import {chaosGameFinal} from "./chaosGameFinal" +import {CoefEditor} from "./CoefEditor" +import {transformPost} from "./post"; +import {buildTransform} from "./buildTransform"; + +export default function FlamePost() { + const {width, height, setPainter} = useContext(PainterContext); + + const [xform1CoefsPost, setXform1PostCoefs] = useState(xform1CoefsPostDefault); + const [xform2CoefsPost, setXform2PostCoefs] = useState(xform2CoefsPostDefault); + const [xform3CoefsPost, setXform3PostCoefs] = useState(xform3CoefsPostDefault); + + const identityXform: Transform = (x, y) => [x, y]; + + useEffect(() => setPainter(chaosGameFinal(width, height, [ + [xform1Weight, transformPost(buildTransform(xform1Coefs, xform1Variations), xform1CoefsPost)], + [xform2Weight, transformPost(buildTransform(xform2Coefs, xform2Variations), xform2CoefsPost)], + [xform3Weight, transformPost(buildTransform(xform3Coefs, xform3Variations), xform3CoefsPost)] + ], identityXform)), [xform1CoefsPost, xform2CoefsPost, xform3CoefsPost]); + + return ( + <> + + + + + ) +} \ No newline at end of file diff --git a/blog/2024-11-15-playing-with-fire/2-transforms/VariationEditor.tsx b/blog/2024-11-15-playing-with-fire/2-transforms/VariationEditor.tsx new file mode 100644 index 0000000..212ffcf --- /dev/null +++ b/blog/2024-11-15-playing-with-fire/2-transforms/VariationEditor.tsx @@ -0,0 +1,42 @@ +import styles from "../src/css/styles.module.css" + +export interface VariationProps { + linear: number; + julia: number; + popcorn: number; + pdj: number; +} + +export interface Props { + title: String; + variations: VariationProps; + setVariations: (variations: VariationProps) => void; +} + +export const VariationEditor = ({title, variations, setVariations}: Props) => { + return ( +
+

{title}

+
+ Linear: {variations.linear} + setVariations({...variations, linear: Number(e.currentTarget.value)})}/> +
+
+ Julia: {variations.julia} + setVariations({...variations, julia: Number(e.currentTarget.value)})}/> +
+
+ Popcorn: {variations.popcorn} + setVariations({...variations, popcorn: Number(e.currentTarget.value)})}/> +
+
+ PDJ: {variations.pdj} + setVariations({...variations, pdj: Number(e.currentTarget.value)})}/> +
+
+ ) +} \ No newline at end of file diff --git a/blog/2024-11-15-playing-with-fire/2-transforms/blend.ts b/blog/2024-11-15-playing-with-fire/2-transforms/blend.ts index 0f8778e..4f3b0da 100644 --- a/blog/2024-11-15-playing-with-fire/2-transforms/blend.ts +++ b/blog/2024-11-15-playing-with-fire/2-transforms/blend.ts @@ -1,7 +1,10 @@ // hidden-start -import { Variation } from "../src/variation" +import {VariationBlend} from "../src/variationBlend"; // hidden-end -export function blend(x: number, y: number, variations: [number, Variation][]): [number, number] { +export function blend( + x: number, + y: number, + variations: VariationBlend): [number, number] { let [finalX, finalY] = [0, 0]; for (const [weight, variation] of variations) { diff --git a/blog/2024-11-15-playing-with-fire/2-transforms/buildTransform.ts b/blog/2024-11-15-playing-with-fire/2-transforms/buildTransform.ts new file mode 100644 index 0000000..57c1e07 --- /dev/null +++ b/blog/2024-11-15-playing-with-fire/2-transforms/buildTransform.ts @@ -0,0 +1,26 @@ +import {applyCoefs, Coefs} from "../src/coefs"; +import {VariationProps} from "./VariationEditor"; +import {Transform} from "../src/transform"; +import {linear} from "../src/linear"; +import {julia} from "../src/julia"; +import {popcorn} from "../src/popcorn"; +import {pdj} from "../src/pdj"; +import {pdjParams} from "../src/params"; +import {blend} from "./blend"; +import {VariationBlend} from "../src/variationBlend"; + +export function buildBlend(coefs: Coefs, variations: VariationProps): VariationBlend { + return [ + [variations.linear, linear], + [variations.julia, julia], + [variations.popcorn, popcorn(coefs)], + [variations.pdj, pdj(pdjParams)] + ] +} + +export function buildTransform(coefs: Coefs, variations: VariationBlend): Transform { + return (x: number, y: number) => { + [x, y] = applyCoefs(x, y, coefs); + return blend(x, y, variations); + } +} \ No newline at end of file diff --git a/blog/2024-11-15-playing-with-fire/2-transforms/chaosGameFinal.ts b/blog/2024-11-15-playing-with-fire/2-transforms/chaosGameFinal.ts new file mode 100644 index 0000000..910eba6 --- /dev/null +++ b/blog/2024-11-15-playing-with-fire/2-transforms/chaosGameFinal.ts @@ -0,0 +1,29 @@ +// hidden-start +import { randomBiUnit } from "../src/randomBiUnit"; +import { randomChoice } from "../src/randomChoice"; +import { plotBinary as plot } from "../src/plotBinary" +import {Transform} from "../src/transform"; +const iterations = 500_000; +const step = 1000; +// hidden-end +export function* chaosGameFinal(width: number, height: number, transforms: [number, Transform][], final: Transform) { + let image = new ImageData(width, height); + let [x, y] = [randomBiUnit(), randomBiUnit()]; + + for (let i = 0; i < iterations; i++) { + const [_, transform] = randomChoice(transforms); + [x, y] = transform(x, y); + + // highlight-start + [x, y] = final(x, y); + // highlight-end + + if (i > 20) + plot(x, y, image); + + if (i % step === 0) + yield image; + } + + yield image; +} \ No newline at end of file diff --git a/blog/2024-11-15-playing-with-fire/2-transforms/index.mdx b/blog/2024-11-15-playing-with-fire/2-transforms/index.mdx index 2826880..5209003 100644 --- a/blog/2024-11-15-playing-with-fire/2-transforms/index.mdx +++ b/blog/2024-11-15-playing-with-fire/2-transforms/index.mdx @@ -37,12 +37,14 @@ the general format. For example: $$ \begin{align*} F_0(x,y) &= \left({x \over 2}, {y \over 2}\right) \\ -&= (a_0 \cdot x + b_0 \cdot y + c_o, d_0 \cdot x + e_0 \cdot y + f_0) \\ +&= (a_0 \cdot x + b_0 \cdot y + c_0, d_0 \cdot x + e_0 \cdot y + f_0) \\ & a_0 = 0.5 \hspace{0.2cm} b_0 = 0 \hspace{0.2cm} c_0 = 0 \\ & d_0 = 0 \hspace{0.2cm} e_0 = 0.5 \hspace{0.2cm} f_0 = 0 \end{align*} $$ +TODO: Explain the applyCoefs function + However, these transforms are pretty boring. We can build more exciting images by using additional functions within the transform. These "sub-functions" are called "variations": @@ -79,10 +81,10 @@ $$ r &= \sqrt{x^2 + y^2} \\ \theta &= \text{arctan}(x / y) \\ \Omega &= \left\{ - \begin{array}{lr} - 0 \hspace{0.4cm} \text{w.p. } 0.5 \\ - \pi \hspace{0.4cm} \text{w.p. } 0.5 \\ - \end{array} +\begin{array}{lr} +0 \hspace{0.4cm} \text{w.p. } 0.5 \\ +\pi \hspace{0.4cm} \text{w.p. } 0.5 \\ +\end{array} \right\} \\ V_{13}(x, y) &= \sqrt{r} \cdot (\text{cos} ( \theta / 2 + \Omega ), \text{sin} ( \theta / 2 + \Omega )) @@ -123,8 +125,7 @@ import pdjSrc from '!!raw-loader!../src/pdj' Now, one variation is fun, but we can also combine variations in a single transform by "blending." Each variation receives the same $x$ and $y$ inputs, and we add together each variation's $x$ and $y$ outputs. -We'll also give each variation a weight ($v_j$) that scales the output, which allows us to control -how much each variation contributes to the transform: +We'll also give each variation a weight ($v_{ij}$) to control how much it contributes to the transform: $$ F_i(x,y) = \sum_{j} v_{ij} V_j(a_i \cdot x + b_i \cdot y + c_i, \hspace{0.2cm} d_i \cdot x + e_i \cdot y + f_i) @@ -136,7 +137,10 @@ import blendSource from "!!raw-loader!./blend"; {blendSource} -And with that in place, we have enough to render a first full fractal flame: +And with that in place, we have enough to render a first full fractal flame. +The sliders below change the variation weights for each transform (the $v_{ij}$ parameters); +try changing them around to see which parts of the image are controlled by +each transform. import BrowserOnly from "@docusaurus/BrowserOnly"; import Canvas from "../src/Canvas"; @@ -144,4 +148,29 @@ import FlameBlend from "./FlameBlend"; {() => } + + +## Post transforms + +After variation blending, we apply a second set of transform coordinates. + +The fractal flame below starts with the same initial transforms/variations as the previous fractal flame, +but allows modifying the post-transform coefficients. + +$$ +P_i(x, y) = (\alpha_i x + \beta_i y + \gamma_i, \delta_i x + \epsilon_i y + \zeta_i) +$$ + +import FlamePost from "./FlamePost"; + + + {() => } + + +## Final transform + +import FlameFinal from "./FlameFinal"; + + + {() => } \ No newline at end of file diff --git a/blog/2024-11-15-playing-with-fire/2-transforms/post.ts b/blog/2024-11-15-playing-with-fire/2-transforms/post.ts new file mode 100644 index 0000000..fc9a777 --- /dev/null +++ b/blog/2024-11-15-playing-with-fire/2-transforms/post.ts @@ -0,0 +1,7 @@ +// hidden-start +import {Coefs} from "../src/coefs"; +import {Transform} from "../src/transform"; +import {applyCoefs} from "../src/coefs"; +// hidden-end +export const transformPost = (transform: Transform, coefs: Coefs): Transform => + (x, y): [number, number] => applyCoefs(...transform(x, y), coefs) \ No newline at end of file diff --git a/blog/2024-11-15-playing-with-fire/src/blend.ts b/blog/2024-11-15-playing-with-fire/src/blend.ts new file mode 100644 index 0000000..e69de29 diff --git a/blog/2024-11-15-playing-with-fire/src/coefs.ts b/blog/2024-11-15-playing-with-fire/src/coefs.ts index 121d451..da7e129 100644 --- a/blog/2024-11-15-playing-with-fire/src/coefs.ts +++ b/blog/2024-11-15-playing-with-fire/src/coefs.ts @@ -3,7 +3,7 @@ export interface Coefs { d: number, e: number, f: number } -export function applyCoefs(x: number, y: number, coefs: Coefs) { +export function applyCoefs(x: number, y: number, coefs: Coefs): [number, number] { return [ (x * coefs.a + y * coefs.b + coefs.c), (x * coefs.d + y * coefs.e + coefs.f) diff --git a/blog/2024-11-15-playing-with-fire/src/css/styles.module.css b/blog/2024-11-15-playing-with-fire/src/css/styles.module.css index c129a5c..f6fe4d3 100644 --- a/blog/2024-11-15-playing-with-fire/src/css/styles.module.css +++ b/blog/2024-11-15-playing-with-fire/src/css/styles.module.css @@ -1,4 +1,23 @@ -.inputDiv { +.inputGroup { + padding: .5em; + margin: .5em; + border: 1px solid; + border-radius: var(--ifm-global-radius); + border-color: var(--ifm-color-emphasis-500); +} + +.inputTitle { + border: 0 solid; + border-bottom: 1px solid; + border-color: var(--ifm-color-emphasis-500); + margin-bottom: .5em; +} + +.inputElement { padding-left: .5em; padding-right: 1em; +} + +.inputElement > p { + margin: 0 } \ No newline at end of file diff --git a/blog/2024-11-15-playing-with-fire/src/julia.ts b/blog/2024-11-15-playing-with-fire/src/julia.ts index 19c5040..cd0ede6 100644 --- a/blog/2024-11-15-playing-with-fire/src/julia.ts +++ b/blog/2024-11-15-playing-with-fire/src/julia.ts @@ -3,11 +3,14 @@ import { Variation } from './variation' // hidden-end export const julia: Variation = (x, y) => { const r = Math.sqrt(Math.pow(x, 2) + Math.pow(y, 2)); + const theta = Math.atan2(x, y); const omega = Math.random() > 0.5 ? 0 : Math.PI; + const sqrtR = Math.sqrt(r); + const thetaVal = theta / 2 + omega; return [ - r * Math.cos(theta / 2 + omega), - r * Math.sin(theta / 2 + omega) + sqrtR * Math.cos(thetaVal), + sqrtR * Math.sin(thetaVal) ] } \ No newline at end of file diff --git a/blog/2024-11-15-playing-with-fire/src/params.ts b/blog/2024-11-15-playing-with-fire/src/params.ts index 0dee991..6b0acd4 100644 --- a/blog/2024-11-15-playing-with-fire/src/params.ts +++ b/blog/2024-11-15-playing-with-fire/src/params.ts @@ -4,11 +4,11 @@ */ import { Coefs } from './coefs'; +import {VariationBlend} from "./variationBlend"; import { linear } from './linear' import { julia } from './julia' import { popcorn } from './popcorn' import {pdj, PdjParams} from './pdj' -import {Variation} from "./variation" export const identityCoefs: Coefs = { a: 1, b: 0, c: 0, @@ -25,7 +25,7 @@ export const xform1Coefs = { d: 1.381068, e: -1.381068, f: 0, } export const xform1CoefsPost = identityCoefs; -export const xform1Variations = [ +export const xform1Variations: VariationBlend = [ [1, julia] ] export const xform1Color = 0; @@ -39,7 +39,7 @@ export const xform2CoefsPost = { a: 1, b: 0, c: 0.241352, d: 0, e: 1, f: 0.271521, } -export const xform2Variations = [ +export const xform2Variations: VariationBlend = [ [1, linear], [1, popcorn(xform2Coefs)] ] @@ -51,7 +51,7 @@ export const xform3Coefs = { d: 0.740356, e: -1.455964, f: -0.362059, } export const xform3CoefsPost = identityCoefs; -export const xform3Variations = [ +export const xform3Variations: VariationBlend = [ [1, pdj(pdjParams)] ]; export const xform3Color = 0.349; @@ -61,7 +61,7 @@ export const xformFinalCoefs = { d: 0, e: 2, f: 0 } export const xformFinalCoefsPost = identityCoefs; -export const xformFinalVariations = [ +export const xformFinalVariations: VariationBlend = [ [1, julia] ] export const xformFinalColor = 0; diff --git a/blog/2024-11-15-playing-with-fire/src/variationBlend.ts b/blog/2024-11-15-playing-with-fire/src/variationBlend.ts new file mode 100644 index 0000000..37a24f6 --- /dev/null +++ b/blog/2024-11-15-playing-with-fire/src/variationBlend.ts @@ -0,0 +1,2 @@ +import {Variation} from "./variation"; +export type VariationBlend = [number, Variation][]; \ No newline at end of file