Post/final transform implementation

This commit is contained in:
2024-11-30 17:35:42 -05:00
parent 1aa45e3f59
commit 6c4d73f081
17 changed files with 360 additions and 120 deletions

View File

@ -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 (
<>
<p style={{gridColumn: '1/-1'}}>{title}:</p>
<div className={styles.inputDiv}>
<p>Linear: {variations.linear}</p>
<input type={'range'} min={0} max={1} step={0.01} style={{width: '100%'}} value={variations.linear}
onInput={e => setVariations({...variations, linear: Number(e.currentTarget.value)})}/>
</div>
<div className={styles.inputDiv}>
<p>Julia: {variations.julia}</p>
<input type={'range'} min={0} max={1} step={0.01} style={{width: '100%'}} value={variations.julia}
onInput={e => setVariations({...variations, julia: Number(e.currentTarget.value)})}/>
</div>
<div className={styles.inputDiv}>
<p>Popcorn: {variations.popcorn}</p>
<input type={'range'} min={0} max={1} step={0.01} style={{width: '100%'}} value={variations.popcorn}
onInput={e => setVariations({...variations, popcorn: Number(e.currentTarget.value)})}/>
</div>
<div className={styles.inputDiv}>
<p>PDJ: {variations.pdj}</p>
<input type={'range'} min={0} max={1} step={0.01} style={{width: '100%'}} value={variations.pdj}
onInput={e => setVariations({...variations, pdj: Number(e.currentTarget.value)})}/>
</div>
</>
)
}
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 (
<div style={{paddingTop: '1em', display: 'grid', gridTemplateColumns: 'auto auto auto auto'}}>
{variationEditor("Transform 1", xform1Variations, setXform1Variations)}
{variationEditor("Transform 2", xform2Variations, setXform2Variations)}
{variationEditor("Transform 3", xform3Variations, setXform3Variations)}
</div>
<>
<VariationEditor title={"Transform 1"} variations={xform1Variations} setVariations={setXform1Variations}/>
<VariationEditor title={"Transform 2"} variations={xform2Variations} setVariations={setXform2Variations}/>
<VariationEditor title={"Transform 3"} variations={xform3Variations} setVariations={setXform3Variations}/>
</>
)
}