Sacks Spiral
by Chris Ball
HTML
<svg version="1.1" width="500" height="500" xmlns="http://www.w3.org/2000/svg" id="canvas"></svg>
JavaScript
function numbersUntil(limit, start = 1) {
return Array.from({length: limit}, (_, i) => i + start)
}
function isSquare(n) {
return n > 0 && Math.sqrt(n) % 1 === 0
}
const isPrime = num => {
for (let i = 2, s = Math.sqrt(num); i <= s; i++) {
if (num % i === 0) return false
}
return num > 1
}
function appendSVGChild(elementType, target, attributes = {}, text = '') {
const element = document.createElementNS('http://www.w3.org/2000/svg', elementType)
Object.entries(attributes).map(a => element.setAttribute(a[0],a[1]))
if (text) {
const textNode = document.createTextNode(text)
element.appendChild(textNode)
}
target.appendChild(element)
return element
}
const canvas = document.getElementById('canvas')
const centre = {
x: canvas.getBoundingClientRect().width / 2,
y: canvas.getBoundingClientRect().height / 2
}
const growthFactor = 1.05
function generateSacksSpiral(numbers) {
for (let i = 1; i <= numbers.length; i++) {
const R = Math.sqrt(i)
let theta = R * 2 * Math.PI
let x = R * Math.cos(theta) + centre.x
let y = R * Math.sin(theta) + centre.y
let r = isPrime(i) ? 1 : 0.3
appendSVGChild('circle', canvas, {
cx: x,
cy: y,
r: r
})
}
}
generateSacksSpiral(numbersUntil(5000))