xxxxxxxxxx
188
/*jshint esversion: 9 */
var points; // = [];
function setup() {
colorMode(HSB, 1);
const size = min(windowWidth, windowHeight);
createCanvas(size, size);
// frameRate(20);
}
function update(points) {
points.forEach(p => {
let { x, y, dir, vel } = p;
vel *= pow(mouseX / width, 8);
p.x = fract(p.x + cos(dir * TWO_PI) * vel);
p.y = fract(p.y + sin(dir * TWO_PI) * vel);
});
}
const cosn = (v) => cos(v * TWO_PI) * 0.5 + 0.5;
const invCosn = (v) => 1 - cosn(v);
let t;
let frames = 1000;
function draw() {
t = fract(frameCount / frames);
// if (!movedX && !movedY)
// return;
randomSeed(0);
// if (abs(movedY) > 0.0 * width || !points) {
points = [];
const count = 10000 * mouseY / width;
const dims = floor(pow(count, 0.5));
for (let i = 0; i < count; i++) {
let x= (i % dims) / dims;
let y= floor(i / dims) / dims;
let d = constrain(dist(x,y,0.5,0.5), 0, 1);
d = d < 0.25 ? 1 : 0;
x += d * (random() - 0.5) * 0.01;
y += d * (random() - 0.5) * 0.01;
// if (dist(x,y,0.5,0.5) < 0.333)
points.push({
x: cos(TWO_PI * (1 + 2 * invCosn(t)) * i / count) * 0.333 * (1 - random() * 0.25) + 0.5,
y: sin(TWO_PI * i / count) * 0.333 * (1 - random() * 0.25) + 0.5,
// x, y,
dir: random(),
vel: random(),
});
}
// }
scale(width, height);
background(0,0,0,1);
noStroke();
fill(1);
const divs = [];
// update(points);
const groups = [{
group: points,
min: {x: 0, y: 0 },
max: {x: 1, y: 1 },
depth: 0,
}];
const axes = ["x", "y"]
for (let i = 0; groups.some(g => g.group.length > 1); i++) {
const { group, parent, min, max } = groups.shift();
const axis = axes[i % 2];
let div =
{
subdivide(group, axis),
parent,
min,
max,
axis,
depth: parent ? parent.depth + 1 : 0,
}
divs.push(div);
const { group1, group2, mid } = div;
const min1 = {min };
const max1 = {max };
const min2 = {min };
const max2 = {max };
switch (axis) {
case "x":
max1.x = mid;
min2.x = mid;
break;
case "y":
max1.y = mid;
min2.y = mid;
break;
}
if (group1.length > 1) groups.push({
group: group1,
parent: div,
min: min1,
max: max1,
});
if (group2.length > 1) groups.push({
group: group2,
parent: div,
min: min2,
max: max2,
});
// groups.sort((g1, g2) => g2.group.length - g1.group.length);
}
stroke(1);
strokeCap(SQUARE);
const maxDepth = divs.reduce((tot, d) => Math.max(tot, d.depth), 0);
divs.forEach((d, i) => {
const {dist, axis, mid, parent, min, max, depth} = d;
// const w = 1 / width;
const w = 1 * pow(1 - dist, 1000) / width;
// const w = (10 / depth) / width;
strokeWeight(w);
const axisFlip = axis == "x" ? "y" : "x";
const hue = fract(mid + 0 / 5 + mouseX / height);
// const alpha = 1; //fract(-0.1 + 1 - depth / maxDepth);
const alpha = constrain(1 - (max[axisFlip] - min[axisFlip]) * 10, 0, 1);
stroke(hue, 0.5, 1, alpha);
switch (axis) {
case "x":
line(mid, min.y, mid, max.y);
break;
case "y":
line(min.x, mid, max.x, mid);
break;
}
});
noStroke();
const r = 5 / width;
points.forEach(p => {
// circle(p.x, p.y, r);
});
}
function subdivide(points, axis) {
points.sort((p1, p2) => p1[axis] - p2[axis]);
points = [points];
const group1 = points.splice(0, floor(points.length / 2));
const group2 = points;
let mid, dist;
if (points.length % 2 == 0) {
const midPoint = group2[0];
group1.push(midPoint);
mid = midPoint[axis];
dist = 0;
} else {
const midPoint1 = group1[group1.length - 1];
const midPoint2 = group2[0];
mid = (midPoint1[axis] + midPoint2[axis]) / 2;
dist = abs(midPoint1[axis] - mid);
}
return {
group1,
group2,
mid,
dist,
};
}