-
Notifications
You must be signed in to change notification settings - Fork 0
Commit
This commit does not belong to any branch on this repository, and may belong to a fork outside of the repository.
- Loading branch information
1 parent
ffb3a81
commit c674b1a
Showing
4 changed files
with
186 additions
and
0 deletions.
There are no files selected for viewing
Binary file not shown.
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
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,44 @@ | ||
<!DOCTYPE html> | ||
<html lang="en"> | ||
<head> | ||
<meta name="description" content="In mathematics, a Voronoi diagram is a partition of a plane into regions close to each of a given set of objects. In the simplest case, these objects are just finitely many points in the plane (called seeds, sites, or generators). For each seed there is a corresponding region, called a Voronoi cell, consisting of all points of the plane closer to that seed than to any other. The Voronoi diagram of a set of points is dual to its Delaunay triangulation."> | ||
<meta name="viewport" content="width=device-width, initial-scale=1.0"> | ||
<meta http-equiv="Content-Type" content="text/html; charset=utf-8"> | ||
<title>Voronoi by Nickolas Gupton</title> | ||
<!-- My CSS --> | ||
<link rel="stylesheet" href="./style.css"> | ||
<link rel="apple-touch-icon" sizes="180x180" href="https://nickolas.gupton.xyz/favicons/apple-touch-icon.png"> | ||
<link rel="icon" type="image/png" sizes="32x32" href="https://nickolas.gupton.xyz/favicons/favicon-32x32.png"> | ||
<link rel="icon" type="image/png" sizes="194x194" href="https://nickolas.gupton.xyz/favicons/favicon-194x194.png"> | ||
<link rel="icon" type="image/png" sizes="192x192" href="https://nickolas.gupton.xyz/favicons/android-chrome-192x192.png"> | ||
<link rel="icon" type="image/png" sizes="16x16" href="https://nickolas.gupton.xyz/favicons/favicon-16x16.png"> | ||
<link rel="manifest" href="https://nickolas.gupton.xyz/favicons/site.webmanifest"> | ||
<link rel="mask-icon" href="https://nickolas.gupton.xyz/favicons/safari-pinned-tab.svg" color="#454d6a"> | ||
<link rel="shortcut icon" href="https://nickolas.gupton.xyz/favicons/favicon.ico"> | ||
<meta name="apple-mobile-web-app-title" content="Voronoi"> | ||
<meta name="application-name" content="Voronoi"> | ||
<meta name="msapplication-TileColor" content="#454d6a"> | ||
<meta name="msapplication-TileImage" content="https://nickolas.gupton.xyz/favicons/mstile-144x144.png"> | ||
<meta name="msapplication-config" content="https://nickolas.gupton.xyz/favicons/browserconfig.xml"> | ||
<meta name="theme-color" content="#454d6a"> | ||
<script src="./script.js" defer></script> | ||
<!-- Clarity code for https://nickolas.gupton.xyz/ --> | ||
<script> | ||
(function(c,l,a,r,i,t,y){ | ||
c[a]=c[a]||function(){(c[a].q=c[a].q||[]).push(arguments)}; | ||
t=l.createElement(r);t.async=1;t.src="https://www.clarity.ms/tag/"+i; | ||
y=l.getElementsByTagName(r)[0];y.parentNode.insertBefore(t,y); | ||
})(window, document, "clarity", "script", "4xpup7sywk"); | ||
</script> | ||
</head> | ||
<body> | ||
<h1 style="display:none;">Voronoi by Nickolas Gupton</h1> | ||
|
||
<fieldset> | ||
<legend id="title">Voronoi</legend> | ||
<canvas id="canvas"></canvas> | ||
</fieldset> | ||
|
||
|
||
</body> | ||
</html> |
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
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,97 @@ | ||
'use strict'; | ||
|
||
///// Globals ///// | ||
let ManhattanDistance = false; | ||
let generatingPoints = []; | ||
let voronoiCanvas = document.querySelector('#canvas'); | ||
let voronoiContext = voronoiCanvas && voronoiCanvas.getContext && voronoiCanvas.getContext('2d'); | ||
|
||
///// Main Functions ///// | ||
function getPointFromEvent(ev) { | ||
let rect = voronoiCanvas.getBoundingClientRect(); | ||
return { | ||
color: 'rgb(' + Math.floor(Math.random() * 256) + ', ' + Math.floor(Math.random() * 256) + ', ' + Math.floor(Math.random() * 256) + ')', | ||
x: ev.clientX - rect.left, | ||
y: ev.clientY - rect.top | ||
}; | ||
} | ||
|
||
function updateVoronoiDiagram() { | ||
voronoiCanvas.width = voronoiCanvas.clientWidth; | ||
voronoiCanvas.height = voronoiCanvas.clientHeight; | ||
|
||
// If there are no points, no reason to redraw | ||
if (generatingPoints.length === 0) { | ||
voronoiContext.fillStyle = 'rgb(0, 0, 0)'; | ||
voronoiContext.fillRect(0, 0, voronoiCanvas.width, voronoiCanvas.height); | ||
return; | ||
} | ||
|
||
// Pick a color for each pixel based on the closest point | ||
for (let x = 0; x < voronoiCanvas.width; x += 1) { | ||
for (let y = 0; y < voronoiCanvas.height; y += 1) { | ||
let currentDistance = 0; | ||
let closestDistance = Infinity; | ||
|
||
generatingPoints.forEach(function (currentPoint) { | ||
if (ManhattanDistance) { | ||
currentDistance = (Math.abs(x - currentPoint.x) + Math.abs(y - currentPoint.y)); | ||
} else { | ||
currentDistance = Math.sqrt(Math.pow(x - currentPoint.x, 2) + Math.pow(y - currentPoint.y, 2)); | ||
} | ||
|
||
if (currentDistance < closestDistance) { | ||
closestDistance = currentDistance; | ||
voronoiContext.fillStyle = currentPoint.color; | ||
} | ||
}); | ||
voronoiContext.fillRect(x, y, 1, 1); | ||
} | ||
} | ||
|
||
// Draw the circle around the point | ||
generatingPoints.forEach(function (currentPoint) { | ||
// Black circle | ||
voronoiContext.beginPath(); | ||
voronoiContext.arc(currentPoint.x, currentPoint.y, 7, 0, 2 * Math.PI, false); | ||
voronoiContext.fillStyle = 'black'; | ||
voronoiContext.fill(); | ||
|
||
// White circle | ||
voronoiContext.beginPath(); | ||
voronoiContext.arc(currentPoint.x, currentPoint.y, 5, 0, 2 * Math.PI, false); | ||
voronoiContext.fillStyle = 'white'; | ||
voronoiContext.fill(); | ||
|
||
// Colored circle | ||
voronoiContext.beginPath(); | ||
voronoiContext.arc(currentPoint.x, currentPoint.y, 3, 0, 2 * Math.PI, false); | ||
voronoiContext.fillStyle = currentPoint.color; | ||
voronoiContext.fill(); | ||
}); | ||
} | ||
|
||
function addPoint(ev) { | ||
generatingPoints.push(getPointFromEvent(ev)); | ||
updateVoronoiDiagram(); | ||
} | ||
|
||
function swapDistanceCalculation() { | ||
ManhattanDistance = !ManhattanDistance; | ||
if (ManhattanDistance) { | ||
document.body.style.backgroundColor = 'rgb(66, 7, 122)'; | ||
} else { | ||
document.body.style.backgroundColor = 'rgb(22, 74, 119)'; | ||
} | ||
|
||
updateVoronoiDiagram(); | ||
} | ||
|
||
///// Event listeners ///// | ||
voronoiCanvas.addEventListener('click', (ev) => addPoint(ev), false); | ||
document.querySelector('#title').addEventListener('click', swapDistanceCalculation, false); | ||
window.addEventListener('resize', updateVoronoiDiagram, false); | ||
|
||
///// Run! ///// | ||
// Finally draw for the first time | ||
updateVoronoiDiagram(); |
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
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,45 @@ | ||
* { | ||
margin: 0; | ||
padding: 0; | ||
} | ||
|
||
body { | ||
width: 100vw; | ||
height: 100vh; | ||
background-color: rgb(22, 74, 119); | ||
overflow: hidden; | ||
} | ||
|
||
fieldset { | ||
width: 80vw; | ||
margin-left: 10vw; | ||
height: 80vh; | ||
margin-top: 10vh; | ||
box-shadow: 10px 10px black; | ||
background-color: white; | ||
border-color: white; | ||
border-radius: 10px; | ||
border-style: solid; | ||
border-width: 2px; | ||
} | ||
|
||
legend { | ||
color: black; | ||
text-shadow: 1px 1px gray; | ||
font-family: Arial, Helvetica, sans-serif; | ||
background-color: white; | ||
border-color: white; | ||
padding: 0 5px 0 5px; | ||
font-size: xx-large; | ||
border-radius: 10px; | ||
border-style: solid; | ||
border-width: 2px; | ||
} | ||
|
||
#canvas { | ||
padding: 0; | ||
width: calc(80vw - 20px); | ||
margin-left: 10px; | ||
height: calc(80vh - 60px); | ||
margin-top: 10px; | ||
} |