|
<!DOCTYPE html> |
|
<html> |
|
<head> |
|
<title>Ulam Spiral with D3.js</title> |
|
<script src="http://cdnjs.cloudflare.com/ajax/libs/d3/3.4.13/d3.min.js" charset="utf-8"></script> |
|
</head> |
|
<body bgcolor="gray"> |
|
<div id="graph" style="width: 960px; height: 500px;margin-left: auto; margin-right: auto;"></div> |
|
</body> |
|
<script> |
|
var width = 960; |
|
var height = 500; |
|
var svg = d3.select("#graph").append("svg") |
|
.attr("width", width) |
|
.attr("height", height); |
|
var dx = 20; |
|
var dy = 20; |
|
x0 = width / 2; |
|
y0 = height / 2; |
|
var size = 100; |
|
|
|
function generateBaseArray(n) { |
|
var result = []; |
|
for (var i = 1; i < n; i++) { |
|
result.push(i); |
|
result.push(i); |
|
result.push(-i); |
|
result.push(-i); |
|
} |
|
return result; |
|
} |
|
|
|
var cornerCoordsForX = generateBaseArray(size); |
|
var cornerCoordsForY = generateBaseArray(size); |
|
cornerCoordsForX.unshift(0); |
|
cornerCoordsForY.unshift(0, 0); |
|
|
|
var Position = function (x, y) { |
|
this.x = x; |
|
this.y = y; |
|
} |
|
|
|
var graphData = []; |
|
for (var i = 0; i < size; i++) { |
|
if (graphData.length > 2) { |
|
var last = graphData[graphData.length - 1]; |
|
if (last.x > cornerCoordsForX[i]) { |
|
var dif = last.x - cornerCoordsForX[i]; |
|
for (var j = 1; j < dif; j++) { |
|
graphData.push(new Position(last.x - j, cornerCoordsForY[i])); |
|
} |
|
} |
|
if (last.x < cornerCoordsForX[i]) { |
|
var dif = last.x - cornerCoordsForX[i]; |
|
for (var j = 1; j < -dif; j++) { |
|
graphData.push(new Position(last.x + j, cornerCoordsForY[i])); |
|
} |
|
} |
|
if (last.y > cornerCoordsForY[i]) { |
|
var dif = last.y - cornerCoordsForY[i]; |
|
for (var j = 1; j < dif; j++) { |
|
graphData.push(new Position(cornerCoordsForX[i], last.y - j)); |
|
} |
|
} |
|
if (last.y < cornerCoordsForY[i]) { |
|
var dif = last.y - cornerCoordsForY[i]; |
|
for (var j = 1; j < -dif; j++) { |
|
graphData.push(new Position(cornerCoordsForX[i], last.y + j)); |
|
} |
|
} |
|
} |
|
graphData.push(new Position(cornerCoordsForX[i], cornerCoordsForY[i])); |
|
} |
|
|
|
var primes = []; |
|
function isPrime(n) { |
|
if (n == 1) return false; |
|
var checkPoint = Math.sqrt(n); |
|
for (var i = 0; primes[i] <= checkPoint; i++) { |
|
if (n % primes[i] == 0) { |
|
return false; |
|
} |
|
} |
|
primes.push(n); |
|
return true; |
|
} |
|
|
|
function fontSize(i) { |
|
if (i > 998) { |
|
return "8px"; |
|
} else if (i > 98) { |
|
return "9px"; |
|
} else if (i > 8) { |
|
return "10px"; |
|
} else { |
|
return "11px"; |
|
} |
|
} |
|
|
|
var text = svg.selectAll("text") |
|
.data(graphData) |
|
.enter() |
|
.append("text"); |
|
|
|
var textLabels = text |
|
.attr("x", function (d) { |
|
return d.x * dx + width / 2; |
|
}) |
|
.attr("y", function (d) { |
|
return d.y * dy + height / 2; |
|
}) |
|
.text(function (d, i) { |
|
return i + 1; |
|
}) |
|
.attr("text-anchor", "middle") |
|
.attr("font-family", "helvetica") |
|
.attr("font-size", fontSize(i)) |
|
.attr("fill", function (d, i) { |
|
if (i + 1 == 1) return "red"; |
|
if (isPrime(i + 1)) { |
|
return "yellow"; |
|
} else { |
|
return "black"; |
|
} |
|
}); |
|
|
|
</script> |
|
</html> |