Log density visualization

This commit is contained in:
2024-12-01 21:57:10 -05:00
parent 79b66337e8
commit 2e8a6d1ce7
20 changed files with 206 additions and 194 deletions

View File

@ -1,17 +1,12 @@
import {useContext, useEffect, useState} from "react";
import {Transform} from "../src/transform";
import {
xform1Coefs,
xform1Weight,
xform2Coefs,
xform2Weight,
xform3Coefs,
xform3Weight
} from "../src/params";
import * as params from "../src/params"
import {PainterContext} from "../src/Canvas"
import {buildBlend, buildTransform} from "./buildTransform"
import {chaosGameFinal} from "./chaosGameFinal"
import {VariationEditor, VariationProps} from "./VariationEditor"
import {xform1Weight} from "../src/params";
import {applyTransform} from "@site/blog/2024-11-15-playing-with-fire/src/applyTransform";
import {buildBlend} from "@site/blog/2024-11-15-playing-with-fire/2-transforms/buildBlend";
export default function FlameBlend() {
const {width, height, setPainter} = useContext(PainterContext);
@ -47,11 +42,21 @@ export default function FlameBlend() {
// and swap in identity components for each
const identityXform: Transform = (x, y) => [x, y];
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]);
useEffect(() => {
const transforms: [number, Transform][] = [
[params.xform1Weight, applyTransform(params.xform1Coefs, buildBlend(params.xform1Coefs, xform1Variations))],
[params.xform2Weight, applyTransform(params.xform2Coefs, buildBlend(params.xform2Coefs, xform2Variations))],
[params.xform3Weight, applyTransform(params.xform3Coefs, buildBlend(params.xform3Coefs, xform3Variations))]
]
const gameParams = {
width,
height,
transforms,
final: identityXform
}
setPainter(chaosGameFinal(gameParams));
}, [xform1Variations, xform2Variations, xform3Variations]);
return (
<>

View File

@ -1,40 +1,18 @@
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 * as params from "../src/params";
import {PainterContext} from "../src/Canvas"
import {buildBlend, buildTransform} from "./buildTransform";
import {transformPost} from "./post";
import {buildBlend} from "./buildBlend";
import {chaosGameFinal} from "./chaosGameFinal"
import {VariationEditor, VariationProps} from "./VariationEditor";
import {CoefEditor} from "./CoefEditor";
import {Transform} from "../src/transform";
export const transforms: [number, Transform][] = [
[xform1Weight, transformPost(buildTransform(xform1Coefs, xform1Variations), xform1CoefsPost)],
[xform2Weight, transformPost(buildTransform(xform2Coefs, xform2Variations), xform2CoefsPost)],
[xform3Weight, transformPost(buildTransform(xform3Coefs, xform3Variations), xform3CoefsPost)]
];
import {applyPost, applyTransform} from "../src/applyTransform";
export default function FlameFinal() {
const {width, height, setPainter} = useContext(PainterContext);
const [xformFinalCoefs, setXformFinalCoefs] = useState<Coefs>(xformFinalCoefsDefault);
const resetXformFinalCoefs = () => setXformFinalCoefs(xformFinalCoefsDefault);
const [xformFinalCoefs, setXformFinalCoefs] = useState<Coefs>(params.xformFinalCoefs);
const resetXformFinalCoefs = () => setXformFinalCoefs(params.xformFinalCoefs);
const xformFinalVariationsDefault: VariationProps = {
linear: 0,
@ -45,15 +23,14 @@ export default function FlameFinal() {
const [xformFinalVariations, setXformFinalVariations] = useState<VariationProps>(xformFinalVariationsDefault);
const resetXformFinalVariations = () => setXformFinalVariations(xformFinalVariationsDefault);
const [xformFinalCoefsPost, setXformFinalCoefsPost] = useState<Coefs>(xformFinalCoefsPostDefault);
const resetXformFinalCoefsPost = () => setXformFinalCoefsPost(xformFinalCoefsPostDefault);
const [xformFinalCoefsPost, setXformFinalCoefsPost] = useState<Coefs>(params.xformFinalCoefsPost);
const resetXformFinalCoefsPost = () => setXformFinalCoefsPost(params.xformFinalCoefsPost);
useEffect(() => {
const finalBlend = buildBlend(xformFinalCoefs, xformFinalVariations);
const finalTransform = buildTransform(xformFinalCoefs, finalBlend);
const finalPost = transformPost(finalTransform, xformFinalCoefsPost);
const finalXform = applyPost(xformFinalCoefsPost, applyTransform(xformFinalCoefs, finalBlend));
setPainter(chaosGameFinal(width, height, transforms, finalPost));
setPainter(chaosGameFinal({width, height, transforms: params.xforms, final: finalXform}));
}, [xformFinalCoefs, xformFinalVariations, xformFinalCoefsPost]);
return (

View File

@ -1,45 +1,37 @@
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 * as params from "../src/params";
import {PainterContext} from "../src/Canvas"
import {chaosGameFinal} from "./chaosGameFinal"
import {chaosGameFinal, ChaosGameFinalProps} from "./chaosGameFinal"
import {CoefEditor} from "./CoefEditor"
import {transformPost} from "./post";
import {buildTransform} from "./buildTransform";
import {applyPost, applyTransform} from "@site/blog/2024-11-15-playing-with-fire/src/applyTransform";
export default function FlamePost() {
const {width, height, setPainter} = useContext(PainterContext);
const [xform1CoefsPost, setXform1CoefsPost] = useState<Coefs>(xform1CoefsPostDefault);
const resetXform1CoefsPost = () => setXform1CoefsPost(xform1CoefsPostDefault);
const [xform1CoefsPost, setXform1CoefsPost] = useState<Coefs>(params.xform1CoefsPost);
const resetXform1CoefsPost = () => setXform1CoefsPost(params.xform1CoefsPost);
const [xform2CoefsPost, setXform2CoefsPost] = useState<Coefs>(xform2CoefsPostDefault);
const resetXform2CoefsPost = () => setXform2CoefsPost(xform2CoefsPostDefault);
const [xform2CoefsPost, setXform2CoefsPost] = useState<Coefs>(params.xform2CoefsPost);
const resetXform2CoefsPost = () => setXform2CoefsPost(params.xform2CoefsPost);
const [xform3CoefsPost, setXform3CoefsPost] = useState<Coefs>(xform3CoefsPostDefault);
const resetXform3CoefsPost = () => setXform1CoefsPost(xform3CoefsPostDefault);
const [xform3CoefsPost, setXform3CoefsPost] = useState<Coefs>(params.xform3CoefsPost);
const resetXform3CoefsPost = () => setXform1CoefsPost(params.xform3CoefsPost);
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]);
const gameParams: ChaosGameFinalProps = {
width,
height,
transforms: [
[params.xform1Weight, applyPost(xform1CoefsPost, applyTransform(params.xform1Coefs, params.xform1Variations))],
[params.xform2Weight, applyPost(xform2CoefsPost, applyTransform(params.xform2Coefs, params.xform2Variations))],
[params.xform3Weight, applyPost(xform3CoefsPost, applyTransform(params.xform3Coefs, params.xform3Variations))],
],
final: identityXform
}
useEffect(() => setPainter(chaosGameFinal(gameParams)), [xform1CoefsPost, xform2CoefsPost, xform3CoefsPost]);
return (
<>

View File

@ -1,17 +0,0 @@
// hidden-start
import {VariationBlend} from "../src/variationBlend";
// hidden-end
export function blend(
x: number,
y: number,
variations: VariationBlend): [number, number] {
let [finalX, finalY] = [0, 0];
for (const [weight, variation] of variations) {
const [varX, varY] = variation(x, y);
finalX += weight * varX;
finalY += weight * varY;
}
return [finalX, finalY];
}

View File

@ -1,13 +1,11 @@
import {applyCoefs, Coefs} from "../src/coefs";
import {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";
import {VariationBlend} from "../src/blend";
export function buildBlend(coefs: Coefs, variations: VariationProps): VariationBlend {
return [
@ -16,11 +14,4 @@ export function buildBlend(coefs: Coefs, variations: VariationProps): VariationB
[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);
}
}

View File

@ -3,13 +3,20 @@ 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;
import {ChaosGameWeightedProps} from "../1-introduction/chaosGameWeighted";
// hidden-end
export function* chaosGameFinal(width: number, height: number, transforms: [number, Transform][], final: Transform) {
export type ChaosGameFinalProps = ChaosGameWeightedProps & {
final: Transform,
quality?: number,
step?: number,
}
export function* chaosGameFinal({width, height, transforms, final, quality, step}: ChaosGameFinalProps) {
let image = new ImageData(width, height);
let [x, y] = [randomBiUnit(), randomBiUnit()];
const iterations = (quality ?? 0.5) * width * height;
step = step ?? 1000;
for (let i = 0; i < iterations; i++) {
const [_, transform] = randomChoice(transforms);
[x, y] = transform(x, y);

View File

@ -133,7 +133,7 @@ $$
The formula looks intimidating, but it's not hard to implement:
import blendSource from "!!raw-loader!./blend";
import blendSource from "!!raw-loader!../src/blend";
<CodeBlock language={'typescript'}>{blendSource}</CodeBlock>