Checkpoint for histogram

It takes a lot of render time to get a usable result, and it's not that interesting. Committing so I can save the work if I want to revisit it, but abandoning the idea for now.
This commit is contained in:
2024-12-01 18:17:36 -05:00
parent 06069fdcea
commit 79b66337e8
9 changed files with 192 additions and 153 deletions

View File

@ -1,5 +1,30 @@
import {VictoryArea} from "victory";
import {VictoryChart, VictoryLine, VictoryScatter, VictoryTheme} from "victory";
import {useContext, useEffect, useState} from "react";
import {PainterContext} from "../src/Canvas";
import {chaosGameHistogram} from "./chaosGameHistogram";
import {PlotData, plotHistogram} from "./plotHistogram";
function F() {
return <VictoryArea data={}
function* plotChaosGame(width: number, height: number, setPdf: (data: PlotData) => void, setCdf: (data: PlotData) => void) {
const emptyImage = new ImageData(width, height);
for (let histogram of chaosGameHistogram(width, height)) {
const plotData = plotHistogram(histogram);
setPdf(plotData);
yield emptyImage;
}
}
export default function FlameHistogram() {
const {width, height, setPainter} = useContext(PainterContext);
const [pdfData, setPdfData] = useState<{ x: number, y: number }[]>(null);
useEffect(() => setPainter(plotChaosGame(width, height, setPdfData, null)), []);
return (
<VictoryChart theme={VictoryTheme.clean}>
<VictoryLine
data={pdfData}
interpolation='natural'
/>
</VictoryChart>
)
}

View File

@ -1,35 +0,0 @@
// hidden-start
import {VictoryChart} from "victory";
import {camera, histIndex} from "../src/camera";
// hidden-end
export class PlotHistogram {
public readonly pixels: Uint32Array;
public constructor(private readonly width: number, height: number) {
this.pixels = new Uint32Array(width * height);
}
public plot(x: number, y: number) {
const [pixelX, pixelY] = camera(x, y, this.width);
const pixelIndex = histIndex(pixelX, pixelY, this.width, 1);
this.pixels[pixelIndex] += 1;
}
public getHistogram() {
const data = new Map<number, number>();
this.pixels.forEach(value => {
const bucket = 32 - Math.clz32(value);
if (bucket in data) {
data[bucket] += 1;
} else {
data[bucket] = 1;
}
})
const output: {x: number, y: number}[] = [];
data.forEach((bucket, value) =>
output.push({x: Math.pow(bucket, 2), y: value}));
return output;
}
}

View File

@ -0,0 +1,34 @@
import {plot} from "./plotHistogram";
import {randomBiUnit} from "../src/randomBiUnit";
import {randomChoice} from "../src/randomChoice";
import {buildTransform} from "../2-transforms/buildTransform";
import {transformPost} from "../2-transforms/post";
import {transforms} from "../2-transforms/FlameFinal";
import * as params from "../src/params";
const finalTransform = buildTransform(params.xformFinalCoefs, params.xformFinalVariations);
const finalTransformPost = transformPost(finalTransform, params.xformFinalCoefsPost);
const step = 1000;
const quality = 1;
export function* chaosGameHistogram(width: number, height: number) {
let iterations = quality * width * height;
let histogram = new Uint32Array(width * height);
let [x, y] = [randomBiUnit(), randomBiUnit()];
for (let i = 0; i < iterations; i++) {
const [_, transform] = randomChoice(transforms);
[x, y] = transform(x, y);
[x, y] = finalTransformPost(x, y);
if (i > 20)
plot(x, y, width, histogram);
if (i % step === 0)
yield histogram;
}
yield histogram;
}

View File

@ -23,6 +23,13 @@ We'll render the reference image again, but this time, counting the times
we tried to turn on a pixel.
import CodeBlock from "@theme/CodeBlock";
import plotHistogramSource from "!!raw-loader!./PlotHistogram";
import plotHistogramSource from "!!raw-loader!./plotHistogram";
<CodeBlock language="typescript">{plotHistogramSource}</CodeBlock>
import Canvas from "../src/Canvas";
import FlameHistogram from "./FlameHistogram";
<Canvas width={400} height={400} hidden={true}>
<FlameHistogram/>
</Canvas>

View File

@ -0,0 +1,23 @@
// hidden-start
import {camera, histIndex} from "../src/camera";
// hidden-end
export function plot(x: number, y: number, width: number, hitCount: Uint32Array) {
const [pixelX, pixelY] = camera(x, y, width);
const pixelIndex = histIndex(pixelX, pixelY, width, 1);
hitCount[pixelIndex] += 1;
}
export type PlotData = {x: number, y: number}[];
export function plotHistogram(hitCount: Uint32Array) {
const data = new Map<number, number>();
hitCount.forEach(value => {
const bucket = 32 - Math.clz32(value);
const currentCount = data.get(bucket) ?? 0;
data.set(bucket, currentCount + 1);
})
const output: PlotData = [];
data.forEach((value, bucket) =>
output.push({x: Math.pow(2, bucket), y: value}));
return output;
}