<canvas id='2d'></canvas>
<div id='out'><a target=
"_parent" href='http://codepen.io/raurir/full/rpEDA/'>3d version?</a></div>
xxxxxxxxxx
body { margin:0;padding:20px; background: #666;}
a {text-decoration:none;padding:10px 0;color:#aaa;font-family:courier;}
var con = console;
var maxIterations = 1000;
var iterations = 0;
var runs = 0;
var testSize = 12;
var padding = testSize / 2;
var gridSize = 60;
var maxPaths = 13000;//gridSize * 4;// 500;
// bails at maxPaths attempts... usually almost fills the space, leaving a few pleasant gaps
var px = gridSize / 2;
var py = 0;
var direction = 2;
var canvas = document.getElementById("2d");
canvas.width = canvas.height = gridSize * testSize;
var shape = canvas.getContext("2d");
// var out = document.getElementById("out");
var currentPath = -1;
// var paths = [];
var path;
var grid = [];
for (var i = 0; i < gridSize; i++) {
grid[i] = [];
for (var j = 0; j < gridSize; j++) {
grid[i][j] = 0;
}
}
function drawLayer() {
for (var y = 0; y < gridSize; y++) {
for (var x = 0; x < gridSize; x++) {
shape.fillStyle = "rgba(0,0,0,0.1)";
shape.fillRect(x * testSize + 1, y * testSize + 1, testSize - 2, testSize - 2);
}
}
}
drawLayer()
function drawPath(path) {
// if (path.length == 1) return; // draw single dots???
var colour = ~~((currentPath * 10) % maxPaths / maxPaths * 360);
shape.beginPath();
// shape.strokeStyle = "hsla(" + colour + ",100%,60%,1)";
// shape.strokeStyle = "hsla(" + colour + ",100%,60%,1)";
var brightness = 60 + ~~(Math.random() * 20);
if(Math.random() > 0.95) brightness = 100; // draw an occasional bright mutant
shape.strokeStyle = "hsla(0,0%," + brightness + "%,1)";
shape.lineWidth = 2;
for ( var i = 0, il = path.length; i < il; i++) {
var node = path[i], x = node[0] * testSize + padding, y = node[1] * testSize + padding;
if (i == 0) {
shape.moveTo(x, y);
} else {
shape.lineTo(x, y);
}
}
shape.stroke();
for ( var i = 0, il = path.length; i < il; i++) {
var node = path[i], x = node[0] * testSize + padding, y = node[1] * testSize + padding;
shape.beginPath();
shape.arc(x, y, padding / 2, 0, 2 * Math.PI, false);
// shape.fillStyle = "hsla(" + colour + ",50%,50%,1)";
shape.fillStyle = "hsla(0,0%," + brightness + "%,1)";
shape.fill();
shape.closePath();
shape.beginPath();
shape.arc(x, y, padding / 2 - 2, 0, 2 * Math.PI, false);
shape.fillStyle = "#666";
shape.fill();
shape.closePath();
}
}
function pointValid(x, y) {
return grid[y] != undefined && grid[y][x] != undefined;
}
function pointFree(x, y) {
return pointValid(x, y) && grid[y][x] != 1;
}
function getNextPoint(x, y) {
var newX = x, newY = y, newDir = Math.floor(Math.random() * 3) - 1;
var dir = (4 + direction + newDir) % 4; // make sure dir is not backwards.
direction = dir;
switch (dir) {
case 0: newY--; break; // up
case 1: newX++; break; // right
case 2: newY++; break; // down
case 3: newX--; break; // left
}
var valid = pointValid(newX, newY);
// con.log(taken, newX, newY)
if (valid) {
if (pointFree(newX, newY)) {
return {
x:newX,
y:newY,
direction: dir,
complete: false
}
} else {
return {
x:newX,
y:newY,
direction: dir,
complete: true
}
}
} else {
return getNextPoint(x, y); // try again, with original point.
}
}
function calcSection() {
var nextPoint = getNextPoint(px,py)
if (nextPoint.complete === true) {
drawPath(path);
if (currentPath < maxPaths) {
// newPath();
setTimeout( function() { newPath() }, 10);
}
} else {
px = nextPoint.x;
py = nextPoint.y;
// con.log('nextPoint', px, py)
grid[py][px] = 1;
path.push([px,py]);
// paths[currentPath] = path;
iterations++;
// drawPath(path);
if (iterations < maxIterations ) {
// setTimeout( function() { calcSection() }, 30);
calcSection();
} else {
con.log("iterations reached", iterations, maxIterations);
}
// if (iterations < 60 ) calcSection();
}
}
var startPositions = gridSize * 4;
var start = [];
for ( var i = 0; i < startPositions; i++ ) {
start[i] = i;
}
function newStart() {
if ( currentPath < gridSize * 4 ) { // do a lap around around the edges first...
var startIndex = start[ ~~(Math.random() * start.length) ];
// con.log( start);
// con.log(startIndex);
start.splice(startIndex, 1);
// con.log( start);
startIndex = currentPath;
px = 0;
py = 0;
var edge = Math.floor(startIndex / gridSize);
var remain = startIndex % gridSize;
switch (edge) {
case 0: // top
px = startIndex;
py = 0;
direction = 2;
break;
case 1: // right
px = gridSize - 1;
py = remain;
direction = 3;
break;
case 2: // bottom
px = gridSize - remain;
py = gridSize - 1;
direction = 0;
break;
case 3: // left
px = 0;
py = gridSize - remain;
direction = 1;
break;
}
/*
px = 0 + ~~(Math.random() * (gridSize - 1));
py = 0 + ~~(Math.random() * (gridSize - 1));
var edge = Math.round(Math.random() * 4);
con.log("edge", edge);
switch (edge) {
case 0: py = 0; break; // top
case 1: px = gridSize - 1; break; // right
case 2: py = gridSize - 1; break; // bottom
case 3: px = 0; break; // left
}
*/
} else {
px = ~~(Math.random() * (gridSize - 1));
py = ~~(Math.random() * (gridSize - 1));
direction = ~~(Math.random() * 4);
}
if (!pointFree(px, py) && iterations < maxIterations) {
currentPath++;
iterations++;
// con.log("finding new start!!!");
newStart();
}
}
function newPath() {
currentPath++;
newStart();
iterations = 0;
path = [];
path.push([px,py]);
grid[py][px] = 1;
calcSection();
}
newPath();