const defaultN = 126; var numberToFactor; var showOutlines = true; var checkPrimes = false; var reversePrimes = true; var numberInput, setNumberButton, toggleOutlines, togglePrimeCheck, togglePrimeReverse; function setup() { createCanvas(570, 570); numberInput = createInput(); numberInput.parent('controls'); numberInput.position(20, 0); setNumberButton = createButton('Draw!'); setNumberButton.parent('controls'); setNumberButton.position(numberInput.x + numberInput.width, numberInput.y); setNumberButton.mousePressed(updateNumber); toggleOutlines = createCheckbox('Show Outlines', showOutlines); toggleOutlines.changed(() => { showOutlines = !showOutlines; background(255); redraw(); }); toggleOutlines.position(20, numberInput.y + numberInput.height + 3); toggleOutlines.parent('controls'); togglePrimeCheck = createCheckbox('Mark Primes', checkPrimes); togglePrimeCheck.changed(() => { checkPrimes = !checkPrimes; background(255); redraw(); }); // togglePrimeCheck.position(toggleOutlines.x+toggleOutlines.width+2, toggleOutlines.y); togglePrimeReverse = createCheckbox('Reverse Nesting Order', reversePrimes); togglePrimeReverse.changed(()=>{ reversePrimes = !reversePrimes; background(255); redraw(); }) // togglePrimeReverse.position(togglePrimeCheck.x+togglePrimeCheck.width+2, toggleOutlines.y); background(255); noLoop(); smooth(); numberToFactor = defaultN; } function updateNumber() { numberToFactor = numberInput.value(); //Yuck. background(255); redraw(); } function draw() { let origin = { x: 0.5 * this.width, y: 0.5 * this.height }; let dimens = Math.min(this.width, this.height); let product = primeFactors(numberToFactor); drawProduct(origin, dimens, product); } function drawProduct(origin, dimens, facts) { if (facts.length === 0) { fill(20, 30, 200, 70); stroke(0); ellipse(origin.x, origin.y, 0.7 * dimens, 0.7 * dimens); } else { if (showOutlines) { noFill(); stroke(0, 100, 30, 150); ellipse(origin.x, origin.y, 0.9 * dimens, 0.9 * dimens); } if (checkPrimes && facts.length > 1 && facts[1] == 1) { fill(200, 30, 20); noStroke(); ellipse(origin.x, origin.y, 0.2 * dimens, 0.2 * dimens); facts = facts.slice(0, facts.length - 1); } let p; if (reversePrimes) { p = facts.pop(); } else { p = facts.shift(); } let newDimens = dimens * Math.sin(Math.PI / p) / (1 + Math.sin(Math.PI / p)); for (let i = 0; i < p; i++) { let newOrigin = { ...origin }; newOrigin.x += 0.5 * 0.9 * (dimens - newDimens) * Math.cos(2 * Math.PI * i / p - Math.PI / 2); newOrigin.y += .5 * 0.9 * (dimens - newDimens) * Math.sin(2 * Math.PI * i / p - Math.PI / 2); let facts0 = [...facts]; drawProduct(newOrigin, newDimens, facts0); } } } function primeFactors(N) { let returnable = []; let testFactor = 2; while (N > 1) { if (N % testFactor == 0) { returnable.push(testFactor); N = N / testFactor; } else testFactor++; } if (checkPrimes && returnable.length === 1) returnable.push(1); return returnable; }