Single Spiral from Triskelion 🌀

Just one of the spirals from the "Triskelion 🌀" by Jurgen
Triskelion 🌀

Log in to post a comment.

// Forked from "Triskelion 🌀" by Jurgen
// https://turtletoy.net/turtle/e994e50d7a

const rIncPerRev = 2; //min=2 max=50 step=1
const rMin = 48; //min=5 max=500 step=1
const correctCenter = 1;
const outline = 1;
const hatching = 0; 

// You can find the Turtle API reference here: https://turtletoy.net/syntax
Canvas.setpenopacity(1);

// Global code will be evaluated once.
const turtle = new Turtle();

const add2 = (a, b) => [a[0]+b[0],a[1]+b[1]];
const lenSq2 = (a) => a[0]**2+a[1]**2;
const len2 = (a) => lenSq2(a)**.5;
const rot2 = (a) => [Math.cos(a), -Math.sin(a), Math.sin(a), Math.cos(a)];
const trans2 = (m, a) => [m[0]*a[0]+m[2]*a[1], m[1]*a[0]+m[3]*a[1]];

const spiralPts = spiral(rIncPerRev, rMin, Math.PI, 0.1);
const startR = spiralPts[0][0];
const endR = len2(spiralPts[spiralPts.length - 1]);
const width  = startR + endR * 2;
const height = (width**2 - (width/2)**2)**.5;

const pts = Array.from({length: 1}).flatMap((v, t) => spiralPts.map(p => trans2(rot2(t*4*Math.PI/3), p)).map(p => add2(trans2(rot2(t*4*Math.PI/3), [-width/2, height/3]), p)))
const centerOffset = correctCenter? pts.reduce((p, c) => [[Math.min(p[0][0], c[0]), Math.max(p[0][1], c[0])], [Math.min(p[1][0], c[1]), Math.max(p[1][1], c[1])]], [[0,0],[0,0]]).map(i => (-i[0]-i[1])/2): [0, 0];


const walk = (i) => outline === 0? false: turtle[i==0?'jump':'goto'](add2(centerOffset, pts.shift())) || pts.length > 0;

function spiral(rIncreasePerRev, rMin, angleOne, angleTwo) {
    const result = [];
    const res = 100; //resolution
    
    const phaseOneMax = 2 * Math.PI * Math.ceil(rMin / rIncreasePerRev) + angleOne;
    const phaseTwoMax = 2 * Math.PI * Math.ceil(rMin / rIncreasePerRev) + angleTwo;
    let phase = 0;
    let i = 0;
    while(phase < phaseOneMax || phase < phaseTwoMax) {
        phase = 2 * Math.PI * i / res;
        const r = rIncreasePerRev * i / res;
        if(phase < phaseOneMax) result.unshift([r * -Math.cos(phase), r * Math.sin(phase)]);
        if(phase < phaseTwoMax) result.push([r * Math.cos(phase), r * -Math.sin(phase)]);
        i++;
    }
    result.unshift([(phaseOneMax / (2*Math.PI)) * rIncreasePerRev * -Math.cos(phaseOneMax), (phaseOneMax / (2*Math.PI)) * rIncreasePerRev * Math.sin(phaseOneMax)]);
    result.push([(phaseTwoMax / (2*Math.PI)) * rIncreasePerRev * Math.cos(phaseTwoMax), (phaseTwoMax / (2*Math.PI)) * rIncreasePerRev * -Math.sin(phaseTwoMax)]);
    return result;
}