Skip to content

Instantly share code, notes, and snippets.

@dribnet
Forked from mbostock/.block
Last active January 2, 2017 23:53
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 dribnet/9243c66a8549b31e047c9ea322901149 to your computer and use it in GitHub Desktop.
Save dribnet/9243c66a8549b31e047c9ea322901149 to your computer and use it in GitHub Desktop.
Branched Random Walks
license: gpl-3.0

(click to reload)

A fork of Mike Bostock's branched random walk. The code has been refactored to allow a pen up/down operation, model was paramaterized further, and three variants with slightly different model settings are shown.

/* this is my general purpose random function
*
* random numbers are always paramaterized between min and max.
* however, the "focus" variable allows an interpolation between
* a uniform and gaussian distribution (normal extends
* "focus" standard deviations from center and a focus of 0
* is a uniform distribution).
*/
function focusedRandom(min, max, focus, mean) {
if(max === undefined) {
max = min;
min = 0;
}
if(focus === undefined) {
focus = 1.0;
}
if(mean === undefined) {
mean = (min + max) / 2.0;
}
if(focus == 0) {
return d3.randomUniform(min, max)();
}
else if(focus < 0) {
focus = -1 / focus;
}
sigma = (0.5 * (max - min)) / focus;
val = d3.randomNormal(mean, sigma)();
if (val > min && val < max) {
return val;
}
return d3.randomUniform(min, max)();
}
<!DOCTYPE html>
<meta charset="utf-8">
<canvas width="960" height="500"></canvas>
<script src="https://d3js.org/d3.v4.min.js"></script>
<script language="javascript" type="text/javascript" src="focusedRandom.js"></script>
<script>
var canvas = document.querySelector("canvas"),
context = canvas.getContext("2d"),
width = canvas.width,
height = canvas.height,
tail_y = [0.2 * canvas.height, 0.5 * canvas.height, 0.8 * canvas.height],
randomY = d3.randomNormal(0,1.5),
randomPenToUp = d3.randomUniform(-15, 1),
randomPenToDown = d3.randomUniform(-5, 1);
render();
canvas.onclick = render;
function render() {
context.clearRect(0, 0, width, height);
render_tail(0);
render_tail(1);
render_tail(2);
}
function render_tail(which_tail) {
var length = Math.floor(focusedRandom(80, 1200, 2, 900));
var tail_length = Math.floor(focusedRandom(60, 400, 3, 200));
var tail_every = Math.floor(focusedRandom(1, 30, 4, 4));
var color = d3.scaleSequential(d3.interpolateRainbow).domain([0, length]);
var x_bias = 600 / length;
var local_randomX = d3.randomNormal(x_bias,2);
var x0 = width / 20,
y0 = tail_y[which_tail],
pen_up0 = false,
tail_chunk = Math.floor(tail_length / 20),
mainWalk = randomWalk([[x0, y0, pen_up0, null]], length, local_randomX);
context.lineJoin = "round";
context.lineCap = "round";
context.lineWidth = 1.5;
context.strokeStyle = "black";
renderWalk(mainWalk);
context.globalCompositeOperation = "multiply";
context.lineWidth = 1;
for (var i = tail_every; i < mainWalk.length; i += tail_every) {
var branchHistory = mainWalk.slice(0, i+1)
for (var j = 0; j < 1; ++j) {
context.strokeStyle = color(i);
branchCopy = branchHistory.slice();
for (var k = 0, m = 20; k < m; ++k) {
context.globalAlpha = (m - k - 1) / m;
var pieceWalk = randomWalk(branchCopy, tail_chunk, local_randomX),
pieceEnd = pieceWalk[pieceWalk.length - 1];
renderWalk(pieceWalk);
branchCopy.push(pieceEnd)
}
context.globalAlpha = 1;
}
}
}
function renderWalk(walk) {
var i, n = walk.length;
context.beginPath();
context.moveTo(walk[0][0], walk[0][1]);
for (i = 0; i < n; ++i) {
// check for pen_up
if(walk[i][2]) {
context.moveTo(walk[i][0], walk[i][1]);
}
else {
context.lineTo(walk[i][0], walk[i][1]);
}
}
context.stroke();
}
function randomWalk(history, n, local_randomX) {
var points, i, x, y, pen_up, randomPenFn;
points = new Array(n);
points[0] = history[history.length - 1];
[x, y, pen_up] = points[0];
for (i = 1; i < n; ++i) {
randomPenFn = pen_up ? randomPenToDown : randomPenToUp;
points[i] = [
x += local_randomX(),
y += randomY(),
pen_up ^= (randomPenFn() > 0)
];
}
return points;
}
</script>
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment