Skip to content

Instantly share code, notes, and snippets.

@veltman
Last active September 25, 2020 06:12
Show Gist options
  • Star 2 You must be signed in to star a gist
  • Fork 0 You must be signed in to fork a gist
  • Save veltman/3d1fb70e6993d4eb2eff7112c9e7bcf4 to your computer and use it in GitHub Desktop.
Save veltman/3d1fb70e6993d4eb2eff7112c9e7bcf4 to your computer and use it in GitHub Desktop.
Voronoi relaxation
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="utf-8" />
</head>
<body>
<canvas width="960" height="500"></canvas>
<script src="https://d3js.org/d3.v4.min.js"></script>
<script>
var width = 960,
height = 500,
canvas = document.querySelector("canvas"),
context = canvas.getContext("2d"),
voronoi = d3.voronoi().extent([[-1, -1],[width + 1, height + 1]]);
context.fillStyle = "#ff3d7f";
context.strokeStyle = "#3fb8af";
function relax(points) {
var polygons = voronoi(points).polygons(),
centroids = polygons.map(d3.polygonCentroid),
converged = points.every(function(point, i){
return distance(point, centroids[i]) < 1;
});
fade();
draw(points, polygons);
if (converged) {
setTimeout(reset, 750);
} else {
setTimeout(function(){
relax(centroids);
}, 50);
}
}
function fade() {
var imageData = context.getImageData(0, 0, width, height);
for (var i = 3, l = imageData.data.length; i < l; i += 4) {
imageData.data[i] = Math.max(0, imageData.data[i] - 10);
}
context.putImageData(imageData, 0, 0);
}
function draw(points, polygons) {
context.beginPath();
polygons.forEach(function(polygon){
context.moveTo(polygon[0][0], polygon[0][1]);
polygon.slice(1).forEach(function(point){
context.lineTo(point[0], point[1]);
});
context.lineTo(polygon[0][0], polygon[0][1]);
});
context.stroke();
context.beginPath();
points.forEach(function(point){
context.moveTo(point[0], point[1]);
context.arc(point[0], point[1], 2, 0, 2 * Math.PI);
});
context.fill();
}
function distance(a, b) {
return Math.sqrt(Math.pow(a[0] - b[0], 2) + Math.pow(a[1] - b[1], 2));
}
function reset() {
var points = d3.range(100).map(function(d){
return [Math.random() * width, Math.random() * height];
});
context.clearRect(0, 0, width, height);
draw(points, voronoi(points).polygons());
setTimeout(function(){
relax(points);
}, 750);
}
reset();
</script>
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment