Skip to content

Instantly share code, notes, and snippets.

@Fil
Last active November 18, 2016 15:28
Show Gist options
  • Star 0 You must be signed in to star a gist
  • Fork 0 You must be signed in to fork a gist
  • Save Fil/18071fb99f105fdc0eb094e2f86497ac to your computer and use it in GitHub Desktop.
Save Fil/18071fb99f105fdc0eb094e2f86497ac to your computer and use it in GitHub Desktop.
Brownian Motion Constrained in Rectangle [UNLISTED]
license: gpl-3.0
border: no
scrolling: no
height: 500
<!DOCTYPE html>
<meta charset="utf-8">
<body>
<script src="//d3js.org/d3.v4.js"></script>
<script>
var width = 400 * 1.618,
height = 400,
τ = 2 * Math.PI;
var nodes = d3.range(200).map(function () {
return {
x: width/2 + (-0.5 + Math.random())*150,
y: height/2 + (-0.5 + Math.random())*150
};
});
var force = d3.forceSimulation()
.nodes(nodes.slice())
.force("collide", d3.forceCollide(4))
.force("brownian", function () {
for (var i = 0, n = nodes.length, node, k = 0.1; i < n; ++i) {
if (Math.random() > 1 - k) {
var angle = Math.random() * τ;
node = nodes[i];
node.vx += 0.2 * Math.cos(angle);
node.vy += 0.2 * Math.sin(angle);
}
}
})
.force("bounce-on-container", function () {
for (var i = 0, n = nodes.length, node; i < n; ++i) {
node = nodes[i];
var dx = node.x / width - 1 / 2,
dy = node.y / height - 1 / 2;
if (Math.random() < Math.pow(dx/0.4, 40)) {
node.vx = - dx * 3;
}
if (Math.random() < Math.pow(dy/0.4, 40)) {
node.vy = - dy * 3;
}
}
})
.on("tick", ticked)
.alphaDecay(0)
.velocityDecay(0.001);
var voronoi = d3.voronoi()
.x(function (d) {
return d.x;
})
.y(function (d) {
return d.y;
});
var canvas = d3.select("body").append("canvas")
.attr("width", width)
.attr("height", height);
var context = canvas.node().getContext("2d");
function moved() {
var p1 = d3.mouse(this);
nodes[0].fx = p1[0];
nodes[0].fy = p1[1];
force.alpha(0.1).restart();
}
function urquhart(diagram) {
var urquhart = d3.map();
diagram.links()
.forEach(function (link) {
var v = d3.extent([link.source.index, link.target.index]);
urquhart.set(v, link);
});
urquhart._remove = [];
diagram.triangles()
.forEach(function (t) {
var l = 0,
length = 0,
i = "bleh",
v;
for (var j = 0; j < 3; j++) {
var a = t[j],
b = t[(j + 1) % 3];
v = d3.extent([a.index, b.index]);
length = (a.x - b.x) * (a.x - b.x) + (a.y - b.y) * (a.y - b.y);
if (length > l) {
l = length;
i = v;
}
}
urquhart._remove.push(i);
});
urquhart._remove.forEach(function (i) {
if (urquhart.has(i)) urquhart.remove(i);
});
return urquhart.values();
}
function ticked() {
var diagram = voronoi(nodes);
//var links = diagram.links();
var links = urquhart(diagram);
//var links = [];
context.clearRect(0, 0, width, height);
context.beginPath();
for (var i = 0, n = links.length; i < n; ++i) {
var link = links[i],
dx = link.source.x - link.target.x,
dy = link.source.y - link.target.y;
context.moveTo(link.source.x, link.source.y);
context.lineTo(link.target.x, link.target.y);
}
context.strokeStyle = "#eee";
context.lineWidth = 8;
context.stroke();
context.beginPath();
for (var i = 0, n = links.length; i < n; ++i) {
var link = links[i],
dx = link.source.x - link.target.x,
dy = link.source.y - link.target.y;
context.moveTo(link.source.x, link.source.y);
context.lineTo(link.target.x, link.target.y);
}
context.strokeStyle = "#000";
context.lineWidth = 0.5;
context.stroke();
context.strokeStyle = "#fcc";
context.beginPath();
context.moveTo(width * 0.1, height * 0.1);
context.lineTo(width * 0.1, height * 0.9);
context.lineTo(width * 0.9, height * 0.9);
context.lineTo(width * 0.9, height * 0.1);
context.lineTo(width * 0.1, height * 0.1);
context.lineWidth = 6;
context.stroke()
context.beginPath();
for (var i = 0, n = nodes.length; i < n; ++i) {
var node = nodes[i];
context.moveTo(node.x, node.y);
context.arc(node.x, node.y, 1, 0, τ);
}
context.lineWidth = 1;
context.strokeStyle = "#fff";
context.stroke();
context.fillStyle = "yellow";
context.fill();
}
</script>
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment