Log in to post a comment.

// Halvorsen Attractor - Continuous Flow Adaptation
// A symmetric, three-lobed chaotic system.

const randomize_inputs = 1; // min=0, max=1, step=1 (Use Input, Randomize)
const steps = 30000; // min=1000, max=100000, step=100

// Halvorsen Parameter (Standard is 1.4 or 1.89)
const a_param = 1.89; // min=1.2, max=2.5, step=0.01

// Set pen-related draw stuff
const scale = 5; // min=0.1, max=50, step=0.1
const x_offset = 0; // min=-100, max=100, step=1
const y_offset = 0; // min=-100, max=100, step=1
const opacity = 0.4; // min=0.0, max=1.0, step=0.01
const dt = 0.005; // min=0.001, max=0.05, step=0.001

let a = a_param;

// Simulation State (Initial values x=1, y=0, z=0)
let x = 1.0;
let y = 0.0;
let z = 0.0;

// Randomization logic
if (randomize_inputs == 0) {
    a = 1.2 + Math.random() * 1.0;
}

Canvas.setpenopacity(opacity);
const turtle = new Turtle();
turtle.penup();

// 3D to 2D Projection
function project(currX, currY, currZ) {
    // Halvorsen is large, so we center it by subtracting a mean offset
    // The attractor is roughly centered around (-a, -a, -a)
    let cx = currX + a;
    let cy = currY + a;
    let cz = currZ + a;

    let screenX = (cx - cy) * Math.cos(0.7) * scale + x_offset;
    let screenY = (cz - (cx + cy) * 0.5) * scale + y_offset;
    return [screenX, screenY];
}

let startPos = project(x, y, z);
turtle.jump(startPos[0], startPos[1]);
turtle.pendown();

function walk(i) {
    // 1. Halvorsen Equations
    let dx = -a*x - 4*y - 4*z - y*y;
    let dy = -a*y - 4*z - 4*x - z*z;
    let dz = -a*z - 4*x - 4*y - x*x;

    // 2. Integration
    x += dx * dt;
    y += dy * dt;
    z += dz * dt;

    // 3. Draw
    let pos = project(x, y, z);
    
    // Safety check for divergence
    if (isNaN(x) || Math.abs(x) > 1000) return false;

    turtle.goto(pos[0], pos[1]);

    return i < steps;
}