diff --git a/blog/2024-11-15-playing-with-fire/1-introduction/index.mdx b/blog/2024-11-15-playing-with-fire/1-introduction/index.mdx
index 8887b59..9e6758c 100644
--- a/blog/2024-11-15-playing-with-fire/1-introduction/index.mdx
+++ b/blog/2024-11-15-playing-with-fire/1-introduction/index.mdx
@@ -51,7 +51,7 @@ First, $S$. We're generating images, so everything is in two dimensions: $S \in
all points that are "in the system." To generate our final image, we just plot every point in the system
like a coordinate chart.
-TODO: What is a stationary point? How does it relate to the chaos game?
+TODO: What is a stationary point? How does it relate to the chaos game? Why does the chaos game work?
For example, if we say $S = \{(0,0), (1, 1), (2, 2)\}$, there are three points to plot:
@@ -187,4 +187,6 @@ import Gasket from '!!raw-loader!./Gasket'
Note: The image our chaos game generates is different than the fractal flame paper, but I think the version displayed
here is correct. As confirmation, the next post will re-create the same image using a different method.
-
\ No newline at end of file
+
+
+TODO: Explanation of function weights $w_i$
\ No newline at end of file
diff --git a/blog/2024-11-15-playing-with-fire/2-transforms/BaselineRender.ts b/blog/2024-11-15-playing-with-fire/2-transforms/BaselineRender.ts
new file mode 100644
index 0000000..315aacb
--- /dev/null
+++ b/blog/2024-11-15-playing-with-fire/2-transforms/BaselineRender.ts
@@ -0,0 +1,5 @@
+import {useColorMode, useThemeConfig} from "@docusaurus/theme-common";
+
+export default function BaselineRender({children}) {
+ const {colorMode, setColorMode} = useColorMode();
+}
\ No newline at end of file
diff --git a/blog/2024-11-15-playing-with-fire/2-transforms/baseline.ts b/blog/2024-11-15-playing-with-fire/2-transforms/baseline.ts
new file mode 100644
index 0000000..1708e81
--- /dev/null
+++ b/blog/2024-11-15-playing-with-fire/2-transforms/baseline.ts
@@ -0,0 +1,22 @@
+// hidden-start
+import { Coefs } from './coefs'
+import { Variation } from './variations'
+// hidden-end
+export function applyTransform(
+ x: number,
+ y: number,
+ coefs: Coefs,
+ variations: [number, Variation][])
+{
+ const transformX = coefs.a * x + coefs.b * y + coefs.c;
+ const transformY = coefs.d * x + coefs.e * y + coefs.f;
+
+ var finalX = 0;
+ var finalY = 0;
+ for (const [blend, variation] of variations) {
+ const [variationX, variationY] = variation(transformX, transformY);
+ finalX += blend * variationX;
+ finalY += blend * variationY;
+ }
+ return [finalX, finalY];
+}
\ 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 b67bbdd..ddccc50 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
@@ -25,6 +25,10 @@ $$
F_i(x,y) = (a_i \cdot x + b_i \cdot y + c_i, \hspace{0.2cm} d_i \cdot x + e_i \cdot y + f_i)
$$
+import coefsSrc from '!!raw-loader!../src/coefs'
+
+{coefsSrc}
+
We also introduced the Sierpinski Gasket functions ($F_0$, $F_1$, and $F_2$), demonstrating how they are related to
the general format. For example:
@@ -37,7 +41,7 @@ F_0(x,y) &= \left({x \over 2}, {y \over 2}\right) \\
\end{align*}
$$
-However, these transforms are pretty boring. We can build more exciting images by using some additional functions
+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":
$$
@@ -52,18 +56,18 @@ Our reference image will focus on just four variations:
### Linear (variation 0)
-This variation returns the $x$ and $y$ coordinates as-is. As mentioned, the Sierpinski Gasket is
-a fractal flame using only the linear variation:
+This variation returns the $x$ and $y$ coordinates as-is:
$$
V_0(x,y) = (x,y)
$$
-```typescript
-function linear(x: number, y: number) {
- return [x, y];
-}
-```
+import linearSrc from '!!raw-loader!../src/linear'
+
+{linearSrc}
+
+Before we move on, it's worth mentioning the relationship between this variation and the Sierpinski Gasket.
+Specifically, we can think of the Gasket as a fractal flame that uses only the linear variation.
### Julia (variation 13)
@@ -86,18 +90,9 @@ V_{13}(x, y) &= \sqrt{r} \cdot (\text{cos} ( \theta / 2 + \Omega ), \text{sin} (
\end{align*}
$$
-```typescript
-function julia(x: number, y: number) {
- 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;
+import juliaSrc from '!!raw-loader!../src/julia'
- return [
- r * Math.cos(theta / 2 + omega),
- r * Math.sin(theta / 2 + omega)
- ]
-}
-```
+{juliaSrc}
### Popcorn (variation 17)
@@ -108,14 +103,9 @@ $$
V_{17}(x,y) = (x + c \cdot \text{sin}(\text{tan }3y), y + f \cdot \text{sin}(\text{tan }3x))
$$
-```typescript
-function popcorn(coefs: {c: number, f: number}) {
- return (x: number, y: number) => [
- x + coefs.c * Math.sin(Math.tan(3 * y)),
- y + coefs.f * Math.sin(Math.tan(3 * x))
- ]
-}
-```
+import popcornSrc from '!!raw-loader!../src/popcorn'
+
+{popcornSrc}
### PDJ (variation 24)
@@ -126,11 +116,27 @@ p_1 = \text{pdj.a} \hspace{0.2cm} p_2 = \text{pdj.b} \hspace{0.2cm} p_3 = \text{
V_{24} = (\text{sin}(p_1 \cdot y) - \text{cos}(p_2 \cdot x), \text{sin}(p_3 \cdot x) - \text{cos}(p_4 \cdot y))
$$
-```typescript
-function pdj(a: number, b: number, c: number, d: number) {
- return (x: number, y: number) => [
- Math.sin(a * y) - Math.cos(b * x),
- Math.sin(c * x) - Math.cos(d * y)
- ]
-}
-```
\ No newline at end of file
+import pdjSrc from '!!raw-loader!../src/pdj'
+
+{pdjSrc}
+
+### Blending
+
+Now, one variation is fun, but we can also combine variations in a single transform by "blending."
+First, each variation is assigned a value that describes how much it affects the transform function ($v_j$).
+Afterward, sum up the $x$ and $y$ values respectively:
+
+$$
+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)
+$$
+
+The formula looks intimidating, but it's not hard to implement:
+
+import baselineSrc from '!!raw-loader!./baseline'
+
+{baselineSrc}
+
+TODO: Mention that the Sierpinski Gasket is just a blend with linear weight 1, all others 0. Maybe replace comment above about Sierpinski Gasket and linear transform?
+
+And with that in place, we have enough to render a first full fractal flame:
+
diff --git a/blog/2024-11-15-playing-with-fire/2-transforms/coefs.ts b/blog/2024-11-15-playing-with-fire/src/coefs.ts
similarity index 100%
rename from blog/2024-11-15-playing-with-fire/2-transforms/coefs.ts
rename to blog/2024-11-15-playing-with-fire/src/coefs.ts
diff --git a/blog/2024-11-15-playing-with-fire/src/julia.ts b/blog/2024-11-15-playing-with-fire/src/julia.ts
new file mode 100644
index 0000000..5d21045
--- /dev/null
+++ b/blog/2024-11-15-playing-with-fire/src/julia.ts
@@ -0,0 +1,13 @@
+// hidden-start
+import { Variation } from './variations'
+// 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;
+
+ return [
+ r * Math.cos(theta / 2 + omega),
+ r * Math.sin(theta / 2 + omega)
+ ]
+}
\ No newline at end of file
diff --git a/blog/2024-11-15-playing-with-fire/src/linear.ts b/blog/2024-11-15-playing-with-fire/src/linear.ts
new file mode 100644
index 0000000..cbea1e7
--- /dev/null
+++ b/blog/2024-11-15-playing-with-fire/src/linear.ts
@@ -0,0 +1,4 @@
+// hidden-start
+import {Variation} from "./variations"
+//hidden-end
+export const linear: Variation = (x, y) => [x, y];
\ No newline at end of file
diff --git a/blog/2024-11-15-playing-with-fire/params.ts b/blog/2024-11-15-playing-with-fire/src/params.ts
similarity index 62%
rename from blog/2024-11-15-playing-with-fire/params.ts
rename to blog/2024-11-15-playing-with-fire/src/params.ts
index b18c647..485347d 100644
--- a/blog/2024-11-15-playing-with-fire/params.ts
+++ b/blog/2024-11-15-playing-with-fire/src/params.ts
@@ -3,8 +3,12 @@
* translated into something that's easier to work with.
*/
-import {Coefs, Transform} from "./types";
-import { julia, linear, pdj, popcorn } from "./variation";
+import { Coefs } from './coefs';
+import { Transform } from './transform';
+import { linear } from './linear'
+import { julia } from './julia'
+import { popcorn } from './popcorn'
+import { pdj } from './pdj'
export const identityCoefs: Coefs = {
a: 1, b: 0, c: 0,
@@ -12,53 +16,51 @@ export const identityCoefs: Coefs = {
}
export const xform1Weight = 0.56453495;
-export const xform1: Transform = {
- coefs: {
- a: -1.381068, b: -1.381068, c: 0,
- d: 1.381068, e: -1.381068, f: 0,
- },
- coefsPost: identityCoefs,
- variations: [[1, julia]],
- color: 0
+export const xform1Coefs = {
+ a: -1.381068, b: -1.381068, c: 0,
+ d: 1.381068, e: -1.381068, f: 0,
}
+export const xform1CoefsPost = identityCoefs;
+export const xform1Variations = [
+ [1, julia]
+]
+export const xform1Color = 0;
-const xform2Weight = 0.013135;
-export const xform2: Transform = {
- coefs: {
- a: 0.031393, b: 0.031367, c: 0,
- d: -0.031367, e: 0.031393, f: 0,
- },
- coefsPost: {
- a: 1, b: 0, c: 0.241352,
- d: 0, e: 1, f: 0.271521,
- },
- variations: [
- [1, linear],
- [1, popcorn]
- ],
- color: 0.844
+export const xform2Weight = 0.013135;
+export const xform2Coefs = {
+ a: 0.031393, b: 0.031367, c: 0,
+ d: -0.031367, e: 0.031393, f: 0,
}
+export const xform2CoefsPost = {
+ a: 1, b: 0, c: 0.241352,
+ d: 0, e: 1, f: 0.271521,
+}
+export const xform2Variations = [
+ [1, linear],
+ [1, popcorn(xform2Coefs)]
+]
+export const xform2Color = 0.844;
export const xform3Weight = 0.42233;
-export const xform3: Transform = {
- coefs: {
- a: 1.51523, b: -3.048677, c: 0.724135,
- d: 0.740356, e: -1.455964, f: -0.362059,
- },
- coefsPost: identityCoefs,
- variations: [[1, pdj(1.09358, 2.13048, 2.54127, 2.37267)]],
- color: 0.349
+export const xform3Coefs = {
+ a: 1.51523, b: -3.048677, c: 0.724135,
+ d: 0.740356, e: -1.455964, f: -0.362059,
}
+export const xform3CoefsPost = identityCoefs;
+export const xform3Variations = [
+ [1, pdj(1.09358, 2.13048, 2.54127, 2.37267)]
+];
+export const xform3Color = 0.349;
-export const xformFinal: Transform = {
- coefs: {
- a: 2, b: 0, c: 0,
- d: 0, e: 2, f: 0
- },
- coefsPost: identityCoefs,
- variations: [[1, julia]],
- color: 0
+export const xformFinalCoefs = {
+ a: 2, b: 0, c: 0,
+ d: 0, e: 2, f: 0
}
+export const xformFinalCoefsPost = identityCoefs;
+export const xformFinalVariations = [
+ [1, julia]
+]
+export const xformFinalColor = 0;
export const palette =
"7E3037762C45722B496E2A4E6A2950672853652754632656" +
diff --git a/blog/2024-11-15-playing-with-fire/src/pdj.ts b/blog/2024-11-15-playing-with-fire/src/pdj.ts
new file mode 100644
index 0000000..5360ced
--- /dev/null
+++ b/blog/2024-11-15-playing-with-fire/src/pdj.ts
@@ -0,0 +1,9 @@
+// hidden-start
+import { Variation } from './variations'
+//hidden-end
+export function pdj(a: number, b: number, c: number, d: number): Variation {
+ return (x, y) => [
+ Math.sin(a * y) - Math.cos(b * x),
+ Math.sin(c * x) - Math.cos(d * y)
+ ]
+}
\ No newline at end of file
diff --git a/blog/2024-11-15-playing-with-fire/src/popcorn.ts b/blog/2024-11-15-playing-with-fire/src/popcorn.ts
new file mode 100644
index 0000000..4652960
--- /dev/null
+++ b/blog/2024-11-15-playing-with-fire/src/popcorn.ts
@@ -0,0 +1,10 @@
+// hidden-start
+import {Coefs} from './coefs'
+import {Variation} from './variations'
+// hidden-end
+export function popcorn({c, f}: Coefs): Variation {
+ return (x, y) => [
+ x + c * Math.sin(Math.tan(3 * y)),
+ y + f * Math.sin(Math.tan(3 * x))
+ ];
+}
\ No newline at end of file
diff --git a/blog/2024-11-15-playing-with-fire/src/transform.ts b/blog/2024-11-15-playing-with-fire/src/transform.ts
new file mode 100644
index 0000000..e719c57
--- /dev/null
+++ b/blog/2024-11-15-playing-with-fire/src/transform.ts
@@ -0,0 +1,9 @@
+import { Coefs } from './coefs'
+import { Variation } from './variations'
+
+export interface Transform {
+ coefs: Coefs,
+ variations: [number, Variation][],
+ coefsPost: Coefs,
+ color: number
+}
\ No newline at end of file
diff --git a/blog/2024-11-15-playing-with-fire/src/variations.ts b/blog/2024-11-15-playing-with-fire/src/variations.ts
new file mode 100644
index 0000000..3b90d18
--- /dev/null
+++ b/blog/2024-11-15-playing-with-fire/src/variations.ts
@@ -0,0 +1 @@
+export type Variation = (x: number, y: number) => [number, number];
\ No newline at end of file
diff --git a/blog/2024-11-15-playing-with-fire/types.ts b/blog/2024-11-15-playing-with-fire/types.ts
deleted file mode 100644
index 7d43ec5..0000000
--- a/blog/2024-11-15-playing-with-fire/types.ts
+++ /dev/null
@@ -1,24 +0,0 @@
-/**
- * Affine transformation coefficients
- */
-export type Coefs = {
- a: number;
- b: number;
- c: number;
- d: number;
- e: number;
- f: number;
-};
-
-export type Variation = (
- x: number,
- y: number,
- coefs: Coefs
-) => [number, number];
-
-export type Transform = {
- coefs: Coefs,
- coefsPost: Coefs,
- variations: [number, Variation][],
- color: number
-}
diff --git a/blog/2024-11-15-playing-with-fire/variation.ts b/blog/2024-11-15-playing-with-fire/variation.ts
deleted file mode 100644
index ddf9ce6..0000000
--- a/blog/2024-11-15-playing-with-fire/variation.ts
+++ /dev/null
@@ -1,40 +0,0 @@
-import { Variation } from "./types";
-
-export const linear: Variation = (x, y) => [x, y];
-
-function r(x: number, y: number) {
- return Math.sqrt(Math.pow(x, 2) + Math.pow(y, 2));
-}
-
-function theta(x: number, y: number) {
- return Math.atan2(x, y);
-}
-
-function omega(): number {
- return Math.random() > 0.5 ? Math.PI : 0;
-}
-
-export const julia: Variation = (x, y) => {
- const sqrtR = Math.sqrt(r(x, y));
- const thetaVal = theta(x, y) / 2 + omega();
- return [sqrtR * Math.cos(thetaVal), sqrtR * Math.sin(thetaVal)];
-};
-
-export const popcorn: Variation = (x, y, transformCoefs) => {
- return [
- x + transformCoefs.c * Math.sin(Math.tan(3 * y)),
- y + transformCoefs.f * Math.sin(Math.tan(3 * x)),
- ];
-};
-
-export const pdj: (
- pdjA: number,
- pdjB: number,
- pdjC: number,
- pdjD: number
-) => Variation = (pdjA, pdjB, pdjC, pdjD) => {
- return (x, y) => [
- Math.sin(pdjA * y) - Math.cos(pdjB * x),
- Math.sin(pdjC * x) - Math.cos(pdjD * y),
- ];
-};
diff --git a/docusaurus.config.ts b/docusaurus.config.ts
index e2ee794..72d1a9c 100644
--- a/docusaurus.config.ts
+++ b/docusaurus.config.ts
@@ -81,7 +81,19 @@ const config: Config = {
prism: {
theme: prismThemes.oneLight,
darkTheme: prismThemes.oneDark,
- additionalLanguages: ['bash', 'java', 'julia', 'nasm']
+ additionalLanguages: ['bash', 'java', 'julia', 'nasm'],
+ magicComments: [
+ // Remember to extend the default highlight class name as well!
+ {
+ className: 'theme-code-block-highlighted-line',
+ line: 'highlight-next-line',
+ block: {start: 'highlight-start', end: 'highlight-end'},
+ },
+ {
+ className: 'code-block-hidden',
+ block: {start: 'hidden-start', end: 'hidden-end'}
+ }
+ ]
},
} satisfies Preset.ThemeConfig,
plugins: [require.resolve('docusaurus-lunr-search')],
diff --git a/src/DualImage/index.tsx b/src/DualImage/index.tsx
deleted file mode 100644
index 2e94211..0000000
--- a/src/DualImage/index.tsx
+++ /dev/null
@@ -1,13 +0,0 @@
-import {useColorMode} from "@docusaurus/theme-common";
-import React from "react";
-
-interface Props {
- srcLight: string;
- srcDark: string;
- alt: string;
-}
-const DualImage = ({srcLight, srcDark, alt}: Props) => {
- const {colorMode} = useColorMode();
- return
-}
-export default DualImage;
\ No newline at end of file
diff --git a/src/css/custom.css b/src/css/custom.css
index 7d691f0..9a455f7 100644
--- a/src/css/custom.css
+++ b/src/css/custom.css
@@ -29,4 +29,11 @@ adapted for Victory charts
*/
[data-theme='dark'] .VictoryContainer {
filter: invert(75%) hue-rotate(180deg);
+}
+
+/*
+Custom magic comment for Prism - hide parts of the code in display
+ */
+.code-block-hidden {
+ display: none;
}
\ No newline at end of file