Skip to content

Commit

Permalink
chore(example): remove complex private fields and tweak examples
Browse files Browse the repository at this point in the history
  • Loading branch information
rektdeckard committed Mar 20, 2024
1 parent 7535fca commit a28783e
Show file tree
Hide file tree
Showing 16 changed files with 267 additions and 166 deletions.
111 changes: 76 additions & 35 deletions example/complex.ts
Original file line number Diff line number Diff line change
Expand Up @@ -6,7 +6,7 @@ import { INTERPOLATORS } from "./color";
import { saveFrames, saveVideo } from "./util.ts";
import { Complex } from "../src";

const ENABLE_CAPTURE = true;
const ENABLE_CAPTURE = false;

const { canvas, p, h2, h3 } = van.tags;
const { math, msup, mrow, mo, mi, mn } = van.tagsNS(
Expand Down Expand Up @@ -56,7 +56,7 @@ function Mandelbrot() {
};
const PARAMS = { ...DEFAULT_PARAMS };

const canv = canvas({
let canv: HTMLCanvasElement | OffscreenCanvas = canvas({
width: WIDTH,
height: HEIGHT,
class: "grabbable",
Expand Down Expand Up @@ -87,10 +87,12 @@ function Mandelbrot() {
zoom: PARAMS.zoom,
stride: PARAMS.stride,
iterations: PARAMS.iterations,
exponent: PARAMS.mandel_exponent,
c: PARAMS.julia_c,
});
},
});
const ctx = canv.getContext("2d")!;
let ctx: CanvasRenderingContext2D | OffscreenCanvasRenderingContext2D = canv.getContext("2d")!;

const pane = new Pane({ title: "Parameters" });
const tab = pane.addTab({
Expand All @@ -100,34 +102,34 @@ function Mandelbrot() {
label: "c",
x: { min: -1, max: 1 },
y: { min: -1, max: 1 },
});
}).on("change", draw);
tab.pages[1].addBinding(PARAMS, "mandel_exponent", {
label: "exponent",
min: 2,
max: 10,
step: 1,
});
}).on("change", draw);
tab.on("select", draw);
pane.addBlade({ view: "separator" });
pane.addBinding(PARAMS, "iterations", {
min: 1,
max: 100,
step: 1,
format: (v) => v.toFixed(0),
});
}).on("change", draw);
pane.addBinding(PARAMS, "stride", {
min: 1,
max: 100,
step: 1,
format: (v) => v.toFixed(0),
});
}).on("change", draw);
pane.addBinding(PARAMS, "scale", {
options: Object.keys(INTERPOLATORS).reduce(
(acc, key) => ({ ...acc, [key]: key }),
{}
),
});
pane.addBinding(PARAMS, "invert");
}).on("change", draw);
pane.addBinding(PARAMS, "invert").on("change", draw);
pane.addBlade({ view: "separator" });
pane.addButton({ title: "Reset" }).on("click", reset);

Expand All @@ -148,65 +150,104 @@ function Mandelbrot() {
// PARAMS.julia_c = { x: -0.1838235, y: -0.6681985 };
// }

// {
// tab.pages[1].selected = true;
// tab.pages[0].selected = false;
// PARAMS.iterations = 100;
// PARAMS.stride = 1;
// PARAMS.offset = { x: -19.754255103824594, y: 22.3536824833637 };
// PARAMS.zoom = 0.18129028535257674;
// PARAMS.mandel_exponent = 2;
// PARAMS.scale = "Spectral";
// PARAMS.invert = true;
// }

// {
// tab.pages[0].selected = true;
// tab.pages[1].selected = false;
// PARAMS.iterations = 100;
// PARAMS.stride = 1;
// PARAMS.offset = { x: -3.1557671462338437, y: 0.45462455886752356 };
// PARAMS.zoom = 0.04624599826929624;
// PARAMS.scale = "RdYlBu";
// PARAMS.invert = true;
// PARAMS.julia_c = { x: -0.22058823529411764, y: -0.7270220588235294 };
// }

{
tab.pages[1].selected = true;
tab.pages[0].selected = false;
PARAMS.iterations = 100;
tab.pages[0].selected = true;
tab.pages[1].selected = false;
PARAMS.iterations = 200;
PARAMS.stride = 1;
PARAMS.offset = { x: -19.754255103824594, y: 22.3536824833637 };
PARAMS.zoom = 0.18129028535257674;
PARAMS.mandel_exponent = 2;
PARAMS.scale = "Magma";
PARAMS.offset = { x: -0.08185745207194693, y: 0.02633283452359185 };
PARAMS.zoom = 0.002475803738526237;
PARAMS.scale = "Earthen";
PARAMS.invert = true;
PARAMS.julia_c = { x: -0.20588235294117652, y: 0.8318014705882353 };
}


draw();

canv = new OffscreenCanvas(WIDTH, HEIGHT);
ctx = canv.getContext("2d")!;
saveVideo(canv, () => {
draw();
const { x, y } = PARAMS.offset;
PARAMS.zoom *= ZOOM_SCALE;
PARAMS.offset = { x: x * ZOOM_SCALE, y: y * ZOOM_SCALE };
}, undefined, { fps: 10, quality: 1 });
}, undefined, { fps: 30, count: 600, quality: 1 });
});
}

pane.on("change", draw);
function mandelbrot(iterations: number, scale: number, exponent: number) {
return function(x: number, y: number) {
const c = new Complex(
(x / WIDTH) * scale - scale / 2,
(y / HEIGHT) * scale - scale / 2
);
let z = Complex.from(c);

function divergesIn(x: number, y: number) {
const scale = 4 / PARAMS.zoom;
const c = new Complex(
(x / WIDTH) * scale - scale / 2,
(y / HEIGHT) * scale - scale / 2
);
let z = Complex.from(c);

if (tab.pages[1].selected) {
// MANDELBROT
for (let i = 0; i < PARAMS.iterations; i++) {
z = z.pow(PARAMS.mandel_exponent).add(c);
for (let i = 0; i < iterations; i++) {
z = z.pow(exponent).add(c);
if (Math.sqrt(z.real ** 2 + z.imaginary ** 2) > 2) {
return i;
}
}
} else {
// JULIA

return iterations;
}
}

function julia(iterations: number, scale: number, c: Complex) {
return function(x: number, y: number) {
let z = new Complex(
(x / WIDTH) * scale - scale / 2,
(y / HEIGHT) * scale - scale / 2
);

for (let i = 0; i < PARAMS.iterations; i++) {
z = z.pow(2).add(new Complex(PARAMS.julia_c.x, PARAMS.julia_c.y));
z = z.pow(2).add(c);
if (Math.sqrt(z.real ** 2 + z.imaginary ** 2) > 2) {
return i;
}
}
return iterations;
}
return PARAMS.iterations;
}

function draw() {
const { x: offsetX, y: offsetY } = PARAMS.offset;
const interpolate = INTERPOLATORS[PARAMS.scale];
const scale = 4 / PARAMS.zoom;
const algo = tab.pages[0].selected
? julia(PARAMS.iterations, scale, new Complex(PARAMS.julia_c.x, PARAMS.julia_c.y))
: mandelbrot(PARAMS.iterations, scale, PARAMS.mandel_exponent);

let i: number;
for (let y = 0; y < HEIGHT; y += PARAMS.stride) {
for (let x = 0; x < WIDTH; x += PARAMS.stride) {
const i = divergesIn(
i = algo(
x + offsetX + PARAMS.stride / 2,
y + offsetY + PARAMS.stride / 2
);
Expand Down
2 changes: 1 addition & 1 deletion example/package.json
Original file line number Diff line number Diff line change
Expand Up @@ -13,13 +13,13 @@
"@ffmpeg/ffmpeg": "^0.12.10",
"@ffmpeg/types": "^0.12.2",
"@ffmpeg/util": "^0.12.1",
"@tweakpane/core": "^2.0.3",
"@tweakpane/plugin-essentials": "^0.2.1",
"d3-color": "^3.1.0",
"d3-scale-chromatic": "^3.0.0",
"tweakpane": "^4.0.3"
},
"devDependencies": {
"@tweakpane/core": "^2.0.3",
"@types/d3-color": "^3.1.3",
"@types/d3-scale-chromatic": "^3.0.3"
}
Expand Down
8 changes: 4 additions & 4 deletions example/pnpm-lock.yaml

Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.

30 changes: 30 additions & 0 deletions example/tsconfig.json
Original file line number Diff line number Diff line change
@@ -0,0 +1,30 @@
{
"include": ["src/"],
"compilerOptions": {
"allowSyntheticDefaultImports": true,
"declaration": true,
"emitDeclarationOnly": true,
"esModuleInterop": true,
"isolatedModules": true,
"jsx": "react-jsx",
"lib": ["ESNext", "DOM, DOM.Iterable"],
"module": "ESNext",
"moduleResolution": "node",
"noFallthroughCasesInSwitch": true,
"noImplicitAny": true,
"noImplicitOverride": true,
"noImplicitReturns": true,
"noImplicitThis": true,
"noUnusedLocals": true,
"noUnusedParameters": true,
"outDir": "dist/",
"resolveJsonModule": true,
"rootDir": "src/",
"skipLibCheck": true,
"strictNullChecks": true,
"strictPropertyInitialization": true,
"sourceMap": true,
"strict": true,
"target": "ESNext"
}
}
17 changes: 11 additions & 6 deletions example/util.ts
Original file line number Diff line number Diff line change
Expand Up @@ -76,8 +76,8 @@ export function saveFrames(
}

export async function saveVideo(
canvas: HTMLCanvasElement,
tick: (canvas: HTMLCanvasElement, f: number, dt: number) => void,
canvas: HTMLCanvasElement | OffscreenCanvas,
tick: (canvas: HTMLCanvasElement | OffscreenCanvas, f: number, dt: number) => void,
filename?: string,
options: VideoOptions = {}
) {
Expand All @@ -89,8 +89,8 @@ export async function saveVideo(
const fileName = filename ?? `output.${fileType}`;

const ffmpeg = await (async () => {
const BASE_URL = "";
// const BASE_URL = "https://unpkg.com/@ffmpeg/[email protected]/dist/esm";
// const BASE_URL = "/kdim";
const BASE_URL = "https://unpkg.com/@ffmpeg/[email protected]/dist/esm";
const ffmpeg = new FFmpeg();
await ffmpeg.load({
coreURL: await toBlobURL(`${BASE_URL}/ffmpeg-core.js`, 'text/javascript'),
Expand All @@ -102,15 +102,20 @@ export async function saveVideo(

async function writeFrame(): Promise<void> {
return new Promise((resolve, reject) => {
canvas.toBlob(
canvas instanceof HTMLCanvasElement ? canvas.toBlob(
async (blob) => {
if (!blob) {
reject(new Error("Unable to create Blob from canvas"));
}
const data = await fetchFile(blob!);
await ffmpeg.writeFile(`${f}.png`, data);
resolve();
}, "png", frameOptions.quality);
}, "png", frameOptions.quality) : (async () => {
const blob = await canvas.convertToBlob(frameOptions);
const data = await fetchFile(blob);
await ffmpeg.writeFile(`${f}.png`, data);
resolve();
})();
});
}

Expand Down
2 changes: 1 addition & 1 deletion example/vite.config.ts
Original file line number Diff line number Diff line change
Expand Up @@ -5,6 +5,6 @@ export default defineConfig({
// dynamicImportVarsOptions: {
// exclude: []
// } },
// optimizeDeps: { exclude: ["worker.js"] },
optimizeDeps: { exclude: ["@ffmpeg/ffmpeg", "@ffmpeg/util"] },
base: "https://rektdeckard.github.io/kdim/",
});
5 changes: 3 additions & 2 deletions package.json
Original file line number Diff line number Diff line change
@@ -1,6 +1,6 @@
{
"name": "kdim",
"version": "0.6.5",
"version": "0.6.6",
"description": "Utility data stuctures, math, and types for JS",
"author": {
"name": "Tobias Fried",
Expand Down Expand Up @@ -38,9 +38,10 @@
"build": "vite build && tsc --emitDeclarationOnly",
"test": "vitest",
"coverage": "vitest run --coverage",
"ex": "vite serve ./example",
"ex": "vite serve --force ./example",
"ex:serve": "pnpm ex",
"ex:build": "vite build ./example",
"ex:preview": "pnpm ex:build && vite preview ./example",
"ex:deploy": "pnpm ex:build && gh-pages -d ./example/dist"
},
"devDependencies": {
Expand Down
4 changes: 1 addition & 3 deletions src/data/KDTree.ts
Original file line number Diff line number Diff line change
Expand Up @@ -70,9 +70,7 @@ export class KDTree<K extends number> implements Iterable<Vec<K>> {
this.#dimensions = point.length;
} else if (this.#dimensions !== point.length) {
throw new TypeError(
`Point [${point}] has ${point.length} dimensions, but should have ${
this.#dimensions
}`
`Point [${point}] has ${point.length} dimensions, but should have ${this.#dimensions}`
);
}

Expand Down
Loading

0 comments on commit a28783e

Please sign in to comment.