Voronoi relaxation with Lloyd's algorithm in d3 4.0.
Last active
September 25, 2020 06:12
-
-
Save veltman/3d1fb70e6993d4eb2eff7112c9e7bcf4 to your computer and use it in GitHub Desktop.
Voronoi relaxation
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
<!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