Skip to content

Instantly share code, notes, and snippets.

@mfilippo
Last active May 10, 2018 13:15
Show Gist options
  • Save mfilippo/4f48d2ddbbf3ab4a88598881fcfa60e7 to your computer and use it in GitHub Desktop.
Save mfilippo/4f48d2ddbbf3ab4a88598881fcfa60e7 to your computer and use it in GitHub Desktop.
Spiral of hexagons
license: gpl-3.0

This example shows how to use the hex-spiral generator to create spirals of hexagons. The number of hexagons to be used is randomly chosen between 50 and 100 for demonstration purpose. Given the coordinates of the hexagons centers forming a spiral, the hexagons are drawn with d3-hexbin.

var hexspiral = (function () {
var cubeDirections = [
{x:+1, y:-1, z:0},
{x:+1, y:0, z:-1},
{x:0, y:+1, z:-1},
{x:-1, y:+1, z:0},
{x:-1, y:0, z:+1},
{x:0, y:-1, z:+1}
];
function createCube(x, y, z) {
return {'x':x, 'y':y, 'z':z};
}
function cubeAdd(c1, c2) {
return {x:c1.x+c2.x, y:c1.y+c2.y, z:c1.z+c2.z};
}
function cubeScale(c1, scale) {
return {x:c1.x*scale, y:c1.y*scale, z:c1.z*scale};
}
function cubeDirection(direction) {
return cubeDirections[direction];
}
function cubeNeighbor(cube, direction) {
return cubeAdd(cube, cubeDirection(direction));
}
function cubeRing(center, ringRadius) {
var results = [];
var cube = cubeAdd(center, cubeScale(cubeDirection(4), ringRadius));
for (var i = 0; i < 6; i++) {
for (var j = 0; j < ringRadius; j++) {
results.push(cube);
cube = cubeNeighbor(cube, i);
}
}
return results;
}
function cubeSpiral(center, radius) {
var results = [center];
for (var k = 1; k <= radius; k++) {
results = results.concat(cubeRing(center, k));
}
return results;
}
function cubeToCartesian(cube, hexRadius, xOffset, yOffset) {
var cy = 3.0/2 * hexRadius * cube.z;
var cx = Math.sqrt(3) * hexRadius * (parseFloat(cube.z)/2 + cube.x);
return {'x':cx + xOffset, 'y':cy + yOffset};
}
function generateHexCenters(cx, cy, hexRadius, n) {
var k = Math.ceil((-1 + Math.sqrt(1 - 4 * (1 - n) / 3)) / 2);
var spiral = cubeSpiral(createCube(0, 0, 0), k);
var centers = spiral.slice(0, n).map(function(cube) {
return cubeToCartesian(cube, hexRadius, cx, cy);
});
return centers;
}
return {
generateHexCenters: generateHexCenters
}
})();
<!DOCTYPE html>
<style>
.hexagon {
stroke: white;
stroke-width: 0.5px;
}
</style>
<svg width="960" height="500"></svg>
<script src="https://d3js.org/d3.v4.min.js"></script>
<script src="https://d3js.org/d3-hexbin.v0.2.min.js"></script>
<script src="hexspiral.js"></script>
<script>
var svg = d3.select("svg"),
width = +svg.attr("width"),
height = +svg.attr("height");
var minNumber = 50,
maxNumber = 100,
hexNumber = d3.randomUniform(minNumber, maxNumber)(),
hexRadius = 20,
svgCenterX = width / 2,
svgCenterY = height / 2,
scaleColor = d3.scaleSequential(d3.interpolateLab("OrangeRed", "SteelBlue")).domain([0, hexNumber]);
var hexbin = d3.hexbin()
.radius(hexRadius);
var centers = hexspiral.generateHexCenters(svgCenterX, svgCenterY, hexRadius, hexNumber);
svg.selectAll('path')
.data(centers)
.enter()
.append('path')
.attr("class", "hexagon")
.attr("d", function(d) { return "M" + d.x + "," + d.y + hexbin.hexagon(); })
.style('fill', function (d, i) { return scaleColor(i); });
</script>
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment