Skip to content

Instantly share code, notes, and snippets.

@FrissAnalytics
Created September 30, 2018 22:29
Show Gist options
  • Save FrissAnalytics/5b94922783274e99e6cffe76cd3ba268 to your computer and use it in GitHub Desktop.
Save FrissAnalytics/5b94922783274e99e6cffe76cd3ba268 to your computer and use it in GitHub Desktop.
Cushion Voronoi
license: mit

A Voronoi diagram colored with a radial gradient centered on each cell's site. The luminance of each point is proportional to the cost of reaching the nearest site (the darker the color, the higher the cost).

forked from nitaku's block: Cushion Voronoi

svg = d3.select 'svg'
width = svg.node().getBoundingClientRect().width
height = svg.node().getBoundingClientRect().height
defs = svg.append 'defs'
radius = 10
sites_data = d3.range(20).map () ->
return {
x: Math.round(Math.random() * (width - radius * 2) + radius),
y: Math.round(Math.random() * (height - radius * 2) + radius)
}
voronoi = d3.voronoi()
.x (d) -> d.x
.y (d) -> d.y
.extent [[-1, -1], [width + 1, height + 1]]
cells_data = voronoi.polygons(sites_data)
# define cells gradients
gradients = defs.selectAll '.gradient'
.data sites_data
enter_gradients = gradients.enter().append 'radialGradient'
.attrs
class: 'gradient'
gradientUnits: 'userSpaceOnUse'
id: (d,i) -> "gradient_#{i}"
cx: (d) -> d.x
cy: (d) -> d.y
r: 300
enter_gradients.append 'stop'
.attrs
offset: '0%'
'stop-color': 'white'
enter_gradients.append 'stop'
.attrs
offset: '100%'
'stop-color': 'black'
# render cells
cells = svg.selectAll '.cell'
.data cells_data
cells.enter().append 'path'
.attrs
class: 'cell'
d: (d) -> if not d? then null else "M" + d.join("L") + "Z"
fill: (d,i) -> "url(#gradient_#{i})"
# render sites
sites = svg.selectAll '.site'
.data sites_data
sites.enter().append 'circle'
.attrs
class: 'site'
r: radius
cx: (d) -> d.x
cy: (d) -> d.y
body, html {
padding: 0;
margin: 0;
height: 100%;
}
svg {
width: 100%;
height: 100%;
background: white;
}
.site {
fill: #DDD;
stroke: gray;
}
.cell {
shape-rendering: crispEdges;
}
<!DOCTYPE html>
<html>
<head>
<meta charset="utf-8">
<title>Cushion Voronoi</title>
<link type="text/css" href="index.css" rel="stylesheet"/>
<script src="https://d3js.org/d3.v4.min.js"></script>
<script src="https://d3js.org/d3-selection-multi.v0.4.min.js"></script>
</head>
<body>
<svg></svg>
<script src="index.js"></script>
</body>
</html>
// Generated by CoffeeScript 1.10.0
(function() {
var cells, cells_data, defs, enter_gradients, gradients, height, radius, sites, sites_data, svg, voronoi, width;
svg = d3.select('svg');
width = svg.node().getBoundingClientRect().width;
height = svg.node().getBoundingClientRect().height;
defs = svg.append('defs');
radius = 10;
sites_data = d3.range(20).map(function() {
return {
x: Math.round(Math.random() * (width - radius * 2) + radius),
y: Math.round(Math.random() * (height - radius * 2) + radius)
};
});
voronoi = d3.voronoi().x(function(d) {
return d.x;
}).y(function(d) {
return d.y;
}).extent([[-1, -1], [width + 1, height + 1]]);
cells_data = voronoi.polygons(sites_data);
gradients = defs.selectAll('.gradient').data(sites_data);
enter_gradients = gradients.enter().append('radialGradient').attrs({
"class": 'gradient',
gradientUnits: 'userSpaceOnUse',
id: function(d, i) {
return "gradient_" + i;
},
cx: function(d) {
return d.x;
},
cy: function(d) {
return d.y;
},
r: 300
});
enter_gradients.append('stop').attrs({
offset: '0%',
'stop-color': 'white'
});
enter_gradients.append('stop').attrs({
offset: '100%',
'stop-color': 'black'
});
cells = svg.selectAll('.cell').data(cells_data);
cells.enter().append('path').attrs({
"class": 'cell',
d: function(d) {
if (d == null) {
return null;
} else {
return "M" + d.join("L") + "Z";
}
},
fill: function(d, i) {
return "url(#gradient_" + i + ")";
}
});
sites = svg.selectAll('.site').data(sites_data);
sites.enter().append('circle').attrs({
"class": 'site',
r: radius,
cx: function(d) {
return d.x;
},
cy: function(d) {
return d.y;
}
});
}).call(this);
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment