From 79394519c7e9ef68974c05a3023aa2bcb5f86780 Mon Sep 17 00:00:00 2001 From: Bradlee Speice Date: Sun, 2 Jul 2023 19:30:56 +0000 Subject: [PATCH] Refactor to use a step function --- posts/2023/06/flam3/0-utility.tsx | 2 +- posts/2023/06/flam3/1-gasket.ts | 2 +- posts/2023/06/flam3/2a-variations.ts | 38 +++++++++++++++------------- posts/2023/06/flam3/2b-post.ts | 4 ++- posts/2023/06/flam3/2c-final.ts | 24 ++++-------------- posts/2023/06/flam3/index.tsx | 12 ++++++--- 6 files changed, 38 insertions(+), 44 deletions(-) diff --git a/posts/2023/06/flam3/0-utility.tsx b/posts/2023/06/flam3/0-utility.tsx index 556f4cb..113957b 100644 --- a/posts/2023/06/flam3/0-utility.tsx +++ b/posts/2023/06/flam3/0-utility.tsx @@ -28,7 +28,7 @@ export const Canvas: React.FC<{ f: renderFn }> = ({ f }) => { } }); - return ; + return ; }; export function randomInteger(min: number, max: number) { diff --git a/posts/2023/06/flam3/1-gasket.ts b/posts/2023/06/flam3/1-gasket.ts index 6da9bac..3114df2 100644 --- a/posts/2023/06/flam3/1-gasket.ts +++ b/posts/2023/06/flam3/1-gasket.ts @@ -10,7 +10,7 @@ function plot(x: number, y: number, image: ImageData) { // pixelY = Math.floor((y + 1) * image.height / 2) // // However, that produces a mirror image (across both X and Y) - // from the paper. We'll invert X and Y to compensate. + // from the paper. We'll negate X and Y to compensate. // Second, because the gasket solution only contains points in // the range [0, 1), the naive plot above would waste 75% of // the pixels available. We'll keep the shift by 1 (to compensate diff --git a/posts/2023/06/flam3/2a-variations.ts b/posts/2023/06/flam3/2a-variations.ts index b0753c9..87d859e 100644 --- a/posts/2023/06/flam3/2a-variations.ts +++ b/posts/2023/06/flam3/2a-variations.ts @@ -17,7 +17,7 @@ function r(x: number, y: number) { } function theta(x: number, y: number) { - return Math.atan2(x, y); + return Math.atan2(y, x); } function omega(): number { @@ -93,6 +93,18 @@ export function weightedChoice(choices: [number, T][]) { throw "unreachable"; } +export class Flame { + x: number = Math.random() * 2 - 1; + y: number = Math.random() * 2 - 1; + + constructor(public readonly transforms: [number, Transform][]) {} + + step() { + const transform = weightedChoice(this.transforms); + [this.x, this.y] = transform.apply(this.x, this.y); + } +} + export function plot(x: number, y: number, image: ImageData) { const pixelX = Math.floor(((x + 2) * image.width) / 4); const pixelY = Math.floor(((y + 2) * image.height) / 4); @@ -114,23 +126,13 @@ export function plot(x: number, y: number, image: ImageData) { image.data[index + 3] = 0xff; } -export class Flame { - constructor(public readonly transforms: [number, Transform][]) {} +export function render(flame: Flame, quality: number, image: ImageData) { + const iterations = quality * image.width * image.height; - render(quality: number, image: ImageData) { - var x = Math.random() * 2 - 1; - var y = Math.random() * 2 - 1; - - const iter = quality * (image.width * image.height); - for (var i = 0; i < iter; i++) { - const transform = weightedChoice(this.transforms); - - // Play the chaos game - [x, y] = transform.apply(x, y); - - if (i > 20) { - plot(x, y, image); - } + for (var i = 0; i < iterations; i++) { + flame.step(); + if (i > 20) { + plot(flame.x, flame.y, image); } } } @@ -185,5 +187,5 @@ export function renderBaseline(image: ImageData) { [transform3Weight, transform3], ]); - flame.render(1, image); + render(flame, 1, image); } diff --git a/posts/2023/06/flam3/2b-post.ts b/posts/2023/06/flam3/2b-post.ts index 41f639b..a8b22d6 100644 --- a/posts/2023/06/flam3/2b-post.ts +++ b/posts/2023/06/flam3/2b-post.ts @@ -7,6 +7,7 @@ import { julia, popcorn, pdj, + render, transform1Coefs, transform1Weight, transform2Coefs, @@ -75,5 +76,6 @@ export function renderPost(image: ImageData) { [transform2Weight, transform2], [transform3Weight, transform3], ]); - flame.render(1, image); + + render(flame, 1, image); } diff --git a/posts/2023/06/flam3/2c-final.ts b/posts/2023/06/flam3/2c-final.ts index 5c68f9c..541fa79 100644 --- a/posts/2023/06/flam3/2c-final.ts +++ b/posts/2023/06/flam3/2c-final.ts @@ -13,8 +13,7 @@ import { transform3Coefs, transform3Pdj, transform3Weight, - weightedChoice, - plot, + render, } from "./2a-variations"; import { TransformPost, transform2Post } from "./2b-post"; @@ -26,22 +25,9 @@ export class FlameFinal extends Flame { super(transforms); } - render(quality: number, image: ImageData) { - var x = Math.random() * 2 - 1; - var y = Math.random() * 2 - 1; - - const iter = quality * (image.width * image.height); - for (var i = 0; i < iter; i++) { - const transform = weightedChoice(this.transforms); - [x, y] = transform.apply(x, y); - - // This line is the only thing that changes: - [x, y] = this.final.apply(x, y); - - if (i > 20) { - plot(x, y, image); - } - } + step() { + super.step(); + [this.x, this.y] = this.final.apply(this.x, this.y); } } @@ -82,5 +68,5 @@ export function renderFinal(image: ImageData) { transformFinal ); - flame.render(1, image); + render(flame, 1, image); } diff --git a/posts/2023/06/flam3/index.tsx b/posts/2023/06/flam3/index.tsx index bc23633..0b4a26c 100644 --- a/posts/2023/06/flam3/index.tsx +++ b/posts/2023/06/flam3/index.tsx @@ -14,10 +14,14 @@ export default function () { }); return ( - - - - +
+ + +
+
+ + +
); }