http://www.generative-gestaltung.de/2/sketches/?01_P/P_2_2_5_01 witha slightly different algorithm.
Created
December 12, 2018 22:13
-
-
Save Gazzell/5fe8e55e97e91a40c08e09092e816bae to your computer and use it in GitHub Desktop.
circles
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
<canvas id='canvas' width='800' height='800'></canvas> |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
const canvas = document.getElementById('canvas'); | |
const ctx = canvas.getContext('2d'); | |
const width = canvas.width; | |
const height = canvas.height; | |
const maxRadius = 50; | |
const minRadius = 3; | |
const cellSize = maxRadius * 2; | |
const cellsX = Math.ceil(width / cellSize); | |
const cellsY = Math.ceil(height / cellSize); | |
const circleCells = []; | |
for(let i = 0; i < width * height; i++) { | |
circleCells.push([]); | |
} | |
function getCell(x, y) { | |
const cellX = Math.floor(x / cellSize); | |
const cellY = Math.floor(y / cellSize); | |
return cellX + cellY * cellsX; | |
} | |
function getAdjacentCells(x, y) { | |
let cells = []; | |
function tryPushCell(cellToPush) { | |
if (cellToPush >= 0 && cellToPush <= circleCells.length) { | |
circleCells[cellToPush].forEach(circle => cells.push(circle)); | |
} | |
} | |
const cell = getCell(x, y); | |
tryPushCell(cell); | |
tryPushCell(cell - cellsX); | |
tryPushCell(cell + cellsX); | |
if(x > cellSize) { | |
tryPushCell(cell - 1); | |
tryPushCell(cell - 1 - cellsX); | |
tryPushCell(cell - 1 + cellsX); | |
} | |
if(x < width - cellSize) { | |
tryPushCell(cell + 1); | |
tryPushCell(cell + 1 - cellsX); | |
tryPushCell(cell + 1 + cellsX); | |
} | |
return cells; | |
} | |
function getRandomPos() { | |
return { x: Math.random() * width, y: Math.random() * height }; | |
} | |
function drawCircle(x, y, radius) { | |
ctx.strokeStyle = 'black'; | |
ctx.beginPath(); | |
ctx.arc(x, y, radius, 0, 2 * Math.PI); | |
ctx.stroke(); | |
} | |
function drawLine(x, y, x2, y2) { | |
ctx.strokeStyle = 'lime'; | |
ctx.beginPath(); | |
ctx.moveTo(x, y); | |
ctx.lineTo(x2, y2); | |
ctx.stroke(); | |
} | |
function distance(x1, y1, x2, y2) { | |
const x = x2 - x1; | |
const y = y2 - y1; | |
return Math.sqrt(x * x + y * y); | |
} | |
function getClosestCircle(x, y) { | |
const cells = getAdjacentCells(x, y); | |
return cells.reduce((acc, circle) => { | |
if (!acc) { | |
return circle; | |
} | |
return distance(x, y, circle.x, circle.y) - circle.radius < distance(x, y, acc.x, acc.y) - acc.radius? circle : acc; | |
}, null); | |
} | |
function draw () { | |
const pos = getRandomPos(); | |
const closest = getClosestCircle(pos.x, pos.y); | |
let radius = maxRadius; | |
if(closest) { | |
const dist = distance(pos.x, pos.y, closest.x, closest.y); | |
radius = dist < closest.radius + maxRadius ? dist - closest.radius : maxRadius; | |
} | |
if(radius > minRadius) { | |
drawCircle(pos.x, pos.y, radius); | |
if (closest) { | |
drawLine(pos.x, pos.y, closest.x, closest.y); | |
} | |
circleCells[getCell(pos.x, pos.y)].push({ x: pos.x, y:pos.y , radius }); | |
} | |
requestAnimationFrame(draw); | |
} | |
draw(); |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment