From 0cd89ad975fb270dfd8ad77b20e033a1866131c0 Mon Sep 17 00:00:00 2001 From: Sheldan <5037282+Sheldan@users.noreply.github.com> Date: Wed, 4 Feb 2026 20:06:25 +0100 Subject: [PATCH] mandelbrot: adding a simple version of mandelbrot --- .gitignore | 3 +- mandelbrot/package-lock.json | 377 +++++++++++++++++++++++++++++++++++ mandelbrot/package.json | 19 ++ mandelbrot/src/index.html | 22 ++ mandelbrot/src/js/main.js | 90 +++++++++ mandelbrot/vite.config.js | 9 + 6 files changed, 519 insertions(+), 1 deletion(-) create mode 100644 mandelbrot/package-lock.json create mode 100644 mandelbrot/package.json create mode 100644 mandelbrot/src/index.html create mode 100644 mandelbrot/src/js/main.js create mode 100644 mandelbrot/vite.config.js diff --git a/.gitignore b/.gitignore index 7beefaa..a4f16d1 100644 --- a/.gitignore +++ b/.gitignore @@ -1,2 +1,3 @@ /dist/ -.idea \ No newline at end of file +.idea +/**/node_modules/ diff --git a/mandelbrot/package-lock.json b/mandelbrot/package-lock.json new file mode 100644 index 0000000..e8eb450 --- /dev/null +++ b/mandelbrot/package-lock.json @@ -0,0 +1,377 @@ +{ + "name": "mandel-brot", + "version": "1.0.0", + "lockfileVersion": 2, + "requires": true, + "packages": { + "": { + "name": "mandel-brot", + "version": "1.0.0", + "license": "MIT", + "dependencies": { + "canvas-common": "file:../canvas-common" + }, + "devDependencies": { + "vite": "^5.1.5" + } + }, + "../canvas-common": { + "version": "1.0.0", + "license": "MIT" + }, + "node_modules/@esbuild/linux-x64": { + "version": "0.21.5", + "cpu": [ + "x64" + ], + "dev": true, + "license": "MIT", + "optional": true, + "os": [ + "linux" + ], + "engines": { + "node": ">=12" + } + }, + "node_modules/@rollup/rollup-linux-x64-gnu": { + "version": "4.54.0", + "cpu": [ + "x64" + ], + "dev": true, + "license": "MIT", + "optional": true, + "os": [ + "linux" + ] + }, + "node_modules/@rollup/rollup-linux-x64-musl": { + "version": "4.54.0", + "cpu": [ + "x64" + ], + "dev": true, + "license": "MIT", + "optional": true, + "os": [ + "linux" + ] + }, + "node_modules/@types/estree": { + "version": "1.0.8", + "dev": true, + "license": "MIT" + }, + "node_modules/canvas-common": { + "resolved": "../canvas-common", + "link": true + }, + "node_modules/esbuild": { + "version": "0.21.5", + "dev": true, + "hasInstallScript": true, + "license": "MIT", + "bin": { + "esbuild": "bin/esbuild" + }, + "engines": { + "node": ">=12" + }, + "optionalDependencies": { + "@esbuild/aix-ppc64": "0.21.5", + "@esbuild/android-arm": "0.21.5", + "@esbuild/android-arm64": "0.21.5", + "@esbuild/android-x64": "0.21.5", + "@esbuild/darwin-arm64": "0.21.5", + "@esbuild/darwin-x64": "0.21.5", + "@esbuild/freebsd-arm64": "0.21.5", + "@esbuild/freebsd-x64": "0.21.5", + "@esbuild/linux-arm": "0.21.5", + "@esbuild/linux-arm64": "0.21.5", + "@esbuild/linux-ia32": "0.21.5", + "@esbuild/linux-loong64": "0.21.5", + "@esbuild/linux-mips64el": "0.21.5", + "@esbuild/linux-ppc64": "0.21.5", + "@esbuild/linux-riscv64": "0.21.5", + "@esbuild/linux-s390x": "0.21.5", + "@esbuild/linux-x64": "0.21.5", + "@esbuild/netbsd-x64": "0.21.5", + "@esbuild/openbsd-x64": "0.21.5", + "@esbuild/sunos-x64": "0.21.5", + "@esbuild/win32-arm64": "0.21.5", + "@esbuild/win32-ia32": "0.21.5", + "@esbuild/win32-x64": "0.21.5" + } + }, + "node_modules/nanoid": { + "version": "3.3.11", + "dev": true, + "funding": [ + { + "type": "github", + "url": "https://github.com/sponsors/ai" + } + ], + "license": "MIT", + "bin": { + "nanoid": "bin/nanoid.cjs" + }, + "engines": { + "node": "^10 || ^12 || ^13.7 || ^14 || >=15.0.1" + } + }, + "node_modules/picocolors": { + "version": "1.1.1", + "dev": true, + "license": "ISC" + }, + "node_modules/postcss": { + "version": "8.5.6", + "dev": true, + "funding": [ + { + "type": "opencollective", + "url": "https://opencollective.com/postcss/" + }, + { + "type": "tidelift", + "url": "https://tidelift.com/funding/github/npm/postcss" + }, + { + "type": "github", + "url": "https://github.com/sponsors/ai" + } + ], + "license": "MIT", + "dependencies": { + "nanoid": "^3.3.11", + "picocolors": "^1.1.1", + "source-map-js": "^1.2.1" + }, + "engines": { + "node": "^10 || ^12 || >=14" + } + }, + "node_modules/rollup": { + "version": "4.54.0", + "dev": true, + "license": "MIT", + "dependencies": { + "@types/estree": "1.0.8" + }, + "bin": { + "rollup": "dist/bin/rollup" + }, + "engines": { + "node": ">=18.0.0", + "npm": ">=8.0.0" + }, + "optionalDependencies": { + "@rollup/rollup-android-arm-eabi": "4.54.0", + "@rollup/rollup-android-arm64": "4.54.0", + "@rollup/rollup-darwin-arm64": "4.54.0", + "@rollup/rollup-darwin-x64": "4.54.0", + "@rollup/rollup-freebsd-arm64": "4.54.0", + "@rollup/rollup-freebsd-x64": "4.54.0", + "@rollup/rollup-linux-arm-gnueabihf": "4.54.0", + "@rollup/rollup-linux-arm-musleabihf": "4.54.0", + "@rollup/rollup-linux-arm64-gnu": "4.54.0", + "@rollup/rollup-linux-arm64-musl": "4.54.0", + "@rollup/rollup-linux-loong64-gnu": "4.54.0", + "@rollup/rollup-linux-ppc64-gnu": "4.54.0", + "@rollup/rollup-linux-riscv64-gnu": "4.54.0", + "@rollup/rollup-linux-riscv64-musl": "4.54.0", + "@rollup/rollup-linux-s390x-gnu": "4.54.0", + "@rollup/rollup-linux-x64-gnu": "4.54.0", + "@rollup/rollup-linux-x64-musl": "4.54.0", + "@rollup/rollup-openharmony-arm64": "4.54.0", + "@rollup/rollup-win32-arm64-msvc": "4.54.0", + "@rollup/rollup-win32-ia32-msvc": "4.54.0", + "@rollup/rollup-win32-x64-gnu": "4.54.0", + "@rollup/rollup-win32-x64-msvc": "4.54.0", + "fsevents": "~2.3.2" + } + }, + "node_modules/source-map-js": { + "version": "1.2.1", + "dev": true, + "license": "BSD-3-Clause", + "engines": { + "node": ">=0.10.0" + } + }, + "node_modules/vite": { + "version": "5.4.21", + "dev": true, + "license": "MIT", + "dependencies": { + "esbuild": "^0.21.3", + "postcss": "^8.4.43", + "rollup": "^4.20.0" + }, + "bin": { + "vite": "bin/vite.js" + }, + "engines": { + "node": "^18.0.0 || >=20.0.0" + }, + "funding": { + "url": "https://github.com/vitejs/vite?sponsor=1" + }, + "optionalDependencies": { + "fsevents": "~2.3.3" + }, + "peerDependencies": { + "@types/node": "^18.0.0 || >=20.0.0", + "less": "*", + "lightningcss": "^1.21.0", + "sass": "*", + "sass-embedded": "*", + "stylus": "*", + "sugarss": "*", + "terser": "^5.4.0" + }, + "peerDependenciesMeta": { + "@types/node": { + "optional": true + }, + "less": { + "optional": true + }, + "lightningcss": { + "optional": true + }, + "sass": { + "optional": true + }, + "sass-embedded": { + "optional": true + }, + "stylus": { + "optional": true + }, + "sugarss": { + "optional": true + }, + "terser": { + "optional": true + } + } + } + }, + "dependencies": { + "@esbuild/linux-x64": { + "version": "0.21.5", + "dev": true, + "optional": true + }, + "@rollup/rollup-linux-x64-gnu": { + "version": "4.54.0", + "dev": true, + "optional": true + }, + "@rollup/rollup-linux-x64-musl": { + "version": "4.54.0", + "dev": true, + "optional": true + }, + "@types/estree": { + "version": "1.0.8", + "dev": true + }, + "canvas-common": { + "version": "file:../canvas-common" + }, + "esbuild": { + "version": "0.21.5", + "dev": true, + "requires": { + "@esbuild/aix-ppc64": "0.21.5", + "@esbuild/android-arm": "0.21.5", + "@esbuild/android-arm64": "0.21.5", + "@esbuild/android-x64": "0.21.5", + "@esbuild/darwin-arm64": "0.21.5", + "@esbuild/darwin-x64": "0.21.5", + "@esbuild/freebsd-arm64": "0.21.5", + "@esbuild/freebsd-x64": "0.21.5", + "@esbuild/linux-arm": "0.21.5", + "@esbuild/linux-arm64": "0.21.5", + "@esbuild/linux-ia32": "0.21.5", + "@esbuild/linux-loong64": "0.21.5", + "@esbuild/linux-mips64el": "0.21.5", + "@esbuild/linux-ppc64": "0.21.5", + "@esbuild/linux-riscv64": "0.21.5", + "@esbuild/linux-s390x": "0.21.5", + "@esbuild/linux-x64": "0.21.5", + "@esbuild/netbsd-x64": "0.21.5", + "@esbuild/openbsd-x64": "0.21.5", + "@esbuild/sunos-x64": "0.21.5", + "@esbuild/win32-arm64": "0.21.5", + "@esbuild/win32-ia32": "0.21.5", + "@esbuild/win32-x64": "0.21.5" + } + }, + "nanoid": { + "version": "3.3.11", + "dev": true + }, + "picocolors": { + "version": "1.1.1", + "dev": true + }, + "postcss": { + "version": "8.5.6", + "dev": true, + "requires": { + "nanoid": "^3.3.11", + "picocolors": "^1.1.1", + "source-map-js": "^1.2.1" + } + }, + "rollup": { + "version": "4.54.0", + "dev": true, + "requires": { + "@rollup/rollup-android-arm-eabi": "4.54.0", + "@rollup/rollup-android-arm64": "4.54.0", + "@rollup/rollup-darwin-arm64": "4.54.0", + "@rollup/rollup-darwin-x64": "4.54.0", + "@rollup/rollup-freebsd-arm64": "4.54.0", + "@rollup/rollup-freebsd-x64": "4.54.0", + "@rollup/rollup-linux-arm-gnueabihf": "4.54.0", + "@rollup/rollup-linux-arm-musleabihf": "4.54.0", + "@rollup/rollup-linux-arm64-gnu": "4.54.0", + "@rollup/rollup-linux-arm64-musl": "4.54.0", + "@rollup/rollup-linux-loong64-gnu": "4.54.0", + "@rollup/rollup-linux-ppc64-gnu": "4.54.0", + "@rollup/rollup-linux-riscv64-gnu": "4.54.0", + "@rollup/rollup-linux-riscv64-musl": "4.54.0", + "@rollup/rollup-linux-s390x-gnu": "4.54.0", + "@rollup/rollup-linux-x64-gnu": "4.54.0", + "@rollup/rollup-linux-x64-musl": "4.54.0", + "@rollup/rollup-openharmony-arm64": "4.54.0", + "@rollup/rollup-win32-arm64-msvc": "4.54.0", + "@rollup/rollup-win32-ia32-msvc": "4.54.0", + "@rollup/rollup-win32-x64-gnu": "4.54.0", + "@rollup/rollup-win32-x64-msvc": "4.54.0", + "@types/estree": "1.0.8", + "fsevents": "~2.3.2" + } + }, + "source-map-js": { + "version": "1.2.1", + "dev": true + }, + "vite": { + "version": "5.4.21", + "dev": true, + "requires": { + "esbuild": "^0.21.3", + "fsevents": "~2.3.3", + "postcss": "^8.4.43", + "rollup": "^4.20.0" + } + } + } +} diff --git a/mandelbrot/package.json b/mandelbrot/package.json new file mode 100644 index 0000000..ed03814 --- /dev/null +++ b/mandelbrot/package.json @@ -0,0 +1,19 @@ +{ + "name": "mandel-brot", + "version": "1.0.0", + "description": "", + "private": true, + "type": "module", + "main": "index.js", + "scripts": { + "test": "echo \"Error: no test specified\" && exit 1" + }, + "author": "", + "license": "MIT", + "dependencies": { + "canvas-common": "file:../canvas-common" + }, + "devDependencies": { + "vite": "^5.1.5" + } +} diff --git a/mandelbrot/src/index.html b/mandelbrot/src/index.html new file mode 100644 index 0000000..5ae4db2 --- /dev/null +++ b/mandelbrot/src/index.html @@ -0,0 +1,22 @@ + + + + + + mandelBrot + + + + + + + + + diff --git a/mandelbrot/src/js/main.js b/mandelbrot/src/js/main.js new file mode 100644 index 0000000..fa52054 --- /dev/null +++ b/mandelbrot/src/js/main.js @@ -0,0 +1,90 @@ +import { + createRainbowColors, + docReady, getIndexForCoordinate, randomInteger +} from "canvas-common"; + +let canvas; +let ctx; +let imageData = {}; + +let final_data; + +let config = { + size: { + height: window.innerHeight, + width: window.innerWidth + } +}; + + +config.mandelBrot = { + fps: 60, +}; + +// 100 colors +let rainbowColors = createRainbowColors(1/16); + +function translatePoint(x, y) { + return {x: x / (config.size.width / 3), y: y / (config.size.height / 3)} +} + +function setup() { + final_data = imageData.data; + for (let y = -config.size.height / 2; y < config.size.height / 2; y++) { + let yToUse = Math.floor(y) + for (let x = -config.size.width / 2; x < config.size.width / 2; x++) { + let xToUse = Math.floor(x); + let translated = translatePoint(xToUse, yToUse) + let iterations = getIterations(translated.x, translated.y); + let color = rainbowColors[iterations]; + let actualX = x + config.size.width / 2; + let actualY = y + config.size.height / 2; + let index = getIndexForCoordinate(config, actualX, actualY); + final_data[index] = color.r; + final_data[index + 1] = color.g; + final_data[index + 2] = color.b; + final_data[index + 3] = 255; + } + } + ctx.putImageData(imageData, 0, 0); +} + +function getIterations(x, y) { + let z_i = {r: 0, i: 0} + let c_r = x; + let c_i = y; + let visited = {} + let iterations = 0; + for (let i = 0; i < 100; i++) { + z_i = getValue(i, z_i.r, z_i.i, c_r, c_i) + let key = z_i.r + '' + z_i.i; + if (key in visited) { + return 0; + } + iterations = i; + if(z_i.r === Infinity || z_i.i === Infinity) { + return iterations; + } + visited[key] = 1 + } + return iterations; +} + +// 0 + 0.5i +// 0 + 0.5i^2 + 0.5i -> -0.25 + 0.5i +// (-0.25 + 0.5i)^2 + 0.5i -> -0.25 * -0.25 + -0.25 * 0.5i + -0.25 * 0.5i + 0.5i * 0.5i + 0.5i +// -3/16 * -3/16 + - 3/16 * 0.25i - 3/16 * 0.25i + 0.25i * 0.25i + 0.5i +function getValue(i, z_r, z_i, c_r, c_i) { + let iFactor = z_r < 0 ? -1 : 1 + return {r: z_r ** 2 + (Math.abs(z_i ** 2) * -1) + c_r, i: z_i * z_r * 2 + c_i} +} + +docReady(function() { + canvas = document.getElementById('canvas') + canvas.width = config.size.width; + canvas.height = config.size.height; + ctx = canvas.getContext("2d"); + canvas.style.backgroundColor = 'rgba(0, 0, 0, 1)'; + imageData = ctx.getImageData(0, 0, config.size.width, config.size.height); + setup() +}); diff --git a/mandelbrot/vite.config.js b/mandelbrot/vite.config.js new file mode 100644 index 0000000..46ba5ce --- /dev/null +++ b/mandelbrot/vite.config.js @@ -0,0 +1,9 @@ +import { defineConfig } from 'vite' + +export default defineConfig({ + base: './', + root: 'src', + build: { + outDir: '../../dist/mandelbrot' + } +})