Log in to post a comment.

// Sprott B Attractor - Continuous Flow Adaptation
// Based on the structure of a 2D Iterative Map

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

// Sprott B Parameters
const a_param = 0.4; // min=0.0, max=2.0, step=0.01
const b_param = 1.2; // min=0.0, max=5.0, step=0.01
const c_param = 1.0; // min=0.0, max=2.0, step=0.01

// Set pen-related draw stuff
const scale = 12; // min=0.1, max=100, step=0.1
const x_offset = 0; // min=-100, max=100, step=1
const y_offset = -20; // min=-100, max=100, step=1
const opacity = 0.5; // min=0.0, max=1.0, step=0.01
const dt = 0.02; // min=0.001, max=0.1, step=0.001

let params = [a_param, b_param, c_param];

// Simulation State
let x = 0.1;
let y = 0.0;
let z = 0.0;

// Randomization logic (if enabled)
if (randomize_inputs == 0) {
    params[0] = Math.random() * 2;
    params[1] = Math.random() * 5;
    params[2] = Math.random() * 2;
}

// Now we actually have a valid strange attractor, prepare to draw
Canvas.setpenopacity(opacity);
const turtle = new Turtle();
turtle.penup();

// Initial projection
function project(currX, currY, currZ) {
    let screenX = (currX * scale) + x_offset;
    // We combine Z and Y for a 3D perspective
    let screenY = (-currZ * scale) + (currY * (scale/2)) + y_offset;
    return [screenX, screenY];
}

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

// The walk function updates the 3D physics and draws the 2D result
function walk(i) {
    // 1. Compute Derivatives (The "Logic" of Sprott B)
    let dx = params[0] * y * z;
    let dy = x - (params[1] * y);
    let dz = params[2] - (x * y);

    // 2. Integration (Euler Step)
    x += dx * dt;
    y += dy * dt;
    z += dz * dt;

    // 3. Project to Screen
    let pos = project(x, y, z);
    
    // Check for "Blow up" (Safety check)
    if (Math.abs(x) > 1000 || Math.abs(y) > 1000 || Math.abs(z) > 1000) {
        console.log("Attractor diverged to infinity.");
        return false;
    }

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

    return i < steps;
}