Skip to content

Instantly share code, notes, and snippets.

@g-k
Last active October 13, 2015 05:17
Show Gist options
  • Save g-k/4144943 to your computer and use it in GitHub Desktop.
Save g-k/4144943 to your computer and use it in GitHub Desktop.
Animation of Jason Davies' d3.js implementation of Brent Yorgey's factorization diagrams
// http://www.jasondavies.com/factorisation-diagrams/
var primeFactors = function (n) {
var factors = [],
f;
while (n > 1) {
factors.push(f = factor(n));
n /= f;
}
return factors;
};
var factor = function (n) {
if (n % 4 === 0) return 4;
for (var i = 2; i <= n / 2; i++) {
if (n % i === 0) return i;
}
return n;
};
var diagram = function (selection, factors, size) {
console.log(factors);
if (factors.length) {
var n = factors.pop(),
offset = n === 4 ? 45 : n === 2 ? 0 : -90,
radius = n * size / (n + 2),
δy = n & 1 ? (radius / 2) * (1 - Math.cos(Math.PI / n)) : 0;
selection.selectAll("g")
.data(d3.range(n))
.enter().append("g")
.attr("transform", function(d) {
var angle = d * 360 / n + offset;
return "translate(0," + δy + ")rotate(" + angle + ")translate(" + radius + ")rotate(" + -angle + ")";
})
.call(diagram, factors, 2 * size / (n + 2));
} else selection.append("circle").attr("r", size * .9);
};
// ensure that we have requestAnimationFrame
// this is Paul Irish's compatibility shim
if (!window.requestAnimationFrame)
{
window.requestAnimationFrame = (function()
{
return window.webkitRequestAnimationFrame ||
window.mozRequestAnimationFrame ||
window.oRequestAnimationFrame ||
window.msRequestAnimationFrame ||
function(callback,element)
{
window.setTimeout(callback, 1000 / 60);
};
})();
};
var interval = 1000;
var fps = 60;
var lastTime = (new Date).getTime();
var elapsed = 0;
var n = 1;
var width = 800,
height = 800;
var svg = d3.select("#visualization").append("svg")
.attr("width", width)
.attr("height", height);
var text = svg.append("text")
.attr("dy", "1em");
svg = svg.append("g")
.attr("transform", "translate(" + [width / 2, height / 2] + ")");
var draw = function (timestamp) {
var dt = timestamp - lastTime;
requestAnimationFrame(draw);
elapsed += dt;
if (elapsed >= interval) {
elapsed = 0;
text.text(n);
svg.selectAll('circle, g').remove();
svg.datum(n)
.attr('id', function (d) { return d; })
.call(diagram, primeFactors(n), width / 2);
n += 1;
}
lastTime = timestamp;
};
requestAnimationFrame(draw);
<html>
<meta charset='utf-8'>
<head>
<title>Factorization Dance</title>
<link type="text/css" rel="stylesheet" href="style.css">
<script src="//cdnjs.cloudflare.com/ajax/libs/d3/3.0.8/d3.min.js"></script>
</head>
<body>
<h1>Factorization Dance</h1>
Animation
of <a href="http://www.jasondavies.com/factorisation-diagrams/">Jason
Davies' d3.js implementation</a> of Brent
Yorgey's <a href="http://mathlesstraveled.com/2012/10/05/factorization-diagrams/">Factorization
diagrams</a>
(and <a href="http://mathlesstraveled.com/2012/11/05/more-factorization-diagrams/">more</a>).
I originally intended to use the new <a href="http://bost.ocks.org/mike/transition/">d3.js v3
transitions</a>, but haven't thought of a good way to implement meaningful transitions.
<div id="visualization"></div>
<script src="factor-dance.js"></script>
</body>
</html>
body {
font: 14px Helvetica Neue;
text-rendering: optimizeLegibility;
margin-top: 1em;
overflow-y: scroll;
}
svg {
margin: 5px;
}
text {
font-size: 24px;
}
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment