Skip to content

Instantly share code, notes, and snippets.

@clawtros
Last active January 12, 2017 23:19
Show Gist options
  • Save clawtros/b682fc49e4f050488cb593ebbdec8914 to your computer and use it in GitHub Desktop.
Save clawtros/b682fc49e4f050488cb593ebbdec8914 to your computer and use it in GitHub Desktop.
'use strict';
function convolve(arr, vs, size, x, y) {
const hl = parseInt(arr.length / 2);
return arr.map((row, offY)=>row.map((m, offX)=>vs[indexOf(x + offX - hl, y + offY - hl, size)] * m))
}
function position(index, size) {
return [Math.floor(index % size), Math.floor(index / size)]
}
function indexOf(x, y, size) {
var lookupX = toroidClamp(x, size),
lookupY = toroidClamp(y, size);
return lookupX + lookupY * size;
}
function toroidClamp(n, maxN) {
if (n < 0) return maxN + n;
if (n >= maxN) return n - maxN;
return n;
}
function flatten(arr) {
return arr.reduce((a, b) => a.concat(b), []);
}
const ToroidVectorField = function(size, A, B) {
const da = 1,
db = 2,
f = 0.55,
k = 0.062,
laplacianConvolution = [
[0.05, 0.2, 0.05],
[0.2, -1, 0.2],
[0.05, 0.2, 0.05]];
let d = [];
function flatConvolve(idx, arr) {
const p = position(idx, size);
return flatten(convolve(laplacianConvolution, arr, size, p[0], p[1]))
}
function applyConvolve(arr, func) {
return arr.map((v, idx) => func(v, flatConvolve(idx, arr).reduce((a, b) => a + b, 0) / 9, idx))
}
function step(t) {
let last = [];
const nextA = applyConvolve(A, (val, cval, idx) => val + da * ((cval - cval * B[idx] * B[idx]) + f * (1 - cval)) * t),
nextB = applyConvolve(B, (val, cval, idx) => val + (db * (cval + cval * B[idx] * B[idx]) - (k + f)) * t);
return ToroidVectorField(size, nextA, nextB)
}
return { step, size, A, B }
}
var CanvasVisualizer = function(canvas, size) {
var context = canvas.getContext('2d'),
canvasWidth = size,
canvasHeight = size;
canvas.width = canvasWidth;
canvas.height = canvasHeight;
return {
draw: function(vectorField) {
vectorField.B.map((v, idx)=>{
const p = position(idx, vectorField.size),
color = parseInt(((v + vectorField.B[idx]) / 2) * 255);
context.fillStyle = `rgb(${color}, ${color}, 0)`;
// context.fillStyle = `hsl(${color % 360}, 70%, 40%)`;
context.fillRect.apply(context, p.concat([1, 1]))
})
}
}
}
function distance(x1, y1, x2, y2) {
let dx = x1 - x2,
dy = y1 - y2;
return Math.sqrt(dx * dx + dy * dy);
}
function randomField(size) {
const A = new Float32Array(size*size).map(_ => 0),
B = new Float32Array(size*size).map((_, idx) => {
const p = position(idx, size),
d = distance(p[0], p[1], size / 2, size / 2);
return d > 40 || d < 30 || Math.random() < 0.5 ? 1 : 0;
});
return new ToroidVectorField(size, A, B);
}
var canvas = document.createElement('canvas'),
size = 200,
vf = randomField(size),
viz = CanvasVisualizer(canvas, size);
document.body.appendChild(canvas);
function go() {
requestAnimationFrame(go);
viz.draw(vf);
vf = vf.step(0.005)
//viz.draw(vf);
};
go();
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment