### Fake hyperbolic plane ✈️

Just search for the nice values / curves.

```console.clear();

const turtle = new Turtle();
const PI2 = Math.PI*2;

const depth = 5; // min=2, max=100, step=1
const useOddEven = 1; // min=0, max=1, step=1

const innerRadius = 3; // min=0, max=100, step=0.01
const outerRadius = 80; // min=0, max=100, step=0.01

const radiusEasing = 2; // min=0, max=40, step=1

const innerAmount = 1; // min=0, max=100, step=0.1
const outerAmount = 16.7; // min=0, max=100, step=0.1
const amountEasing = 0; // min=0, max=40, step=1
const amountEase = getEasing(amountEasing);
console.log("amountEase: " + amountEase.name);

const innerCircleRadius = 1; // min=0, max=50, step=0.01
const outerCircleRadius = 15.4; // min=0, max=50, step=0.01
const circleRadiusEasing = 0; // min=0, max=40, step=1

function walk(i) {
let r = i/depth;
circles(
i,
lerp(innerAmount, outerAmount, amountEase.fn(r))|0,

return i < depth;
}

function lerp(a, b, r) {
return a + (b - a) * r;
}

let f = 1 / amount;
for (let i = 0; i<amount; i++) {
let t = f * i;
let a = PI2 * t;
if (useOddEven && idx & 1) a += PI2 * f * 0.5;
turtle.jump(pos);
}
}

function getEasing(idx) {
return [
{name: "linear", fn: t => t},
{name: "smoothstep", fn: t => t * t * (3.0 - 2.0 * t)},
{name: "quad in", fn: t => t * t},
{name: "quad out", fn: t => t * (2.0 - t)},
{name: "quad in/out", fn: t => t <= 0.5 ? t * t * 2.0 : 1.0 - (--t) * t * 2.0},
{name: "quad out/in", fn: t => (t < 0.5) ? -0.5 * (t = (t * 2.0)) * (t - 2.0) : 0.5 * (t = (t * 2.0 - 1.0)) * t + 0.5},
{name: "pow in", fn: t => Math.pow(t, 5)},
{name: "pow out", fn: t => 1 - Math.pow(1 - t, 5)},
{name: "sine in", fn: t => 1 - Math.cos((Math.PI * 0.5) * t)},
{name: "sine out", fn: t => Math.sin(Math.PI * 0.5 * t)},
{name: "sine in/out", fn: t => .5 - Math.cos(Math.PI * t) / 2.0},
{name: "sine out/in", fn: t => { if (t == 0.0) return 0.0
else if (t == 1.0) return 1.0
else return (t < 0.5) ? 0.5 * Math.sin((t * 2.0) * Math.PI*0.5) : -0.5 * Math.cos((t * 2.0 - 1.0) * Math.PI*0.5) + 1.0
}},
{name: "circ in", fn: t => 1.0 - Math.sqrt(1.0 - t * t)},
{name: "circ out", fn: t => { --t; return Math.sqrt(1.0 - t * t) }},
{name: "circ in/out", fn: t => t <= 0.5 ? (Math.sqrt(1.0 - t * t * 4.0) - 1.0) / -2.0 : (Math.sqrt(1.0 - (t * 2.0 - 2.0) * (t * 2.0 - 2.0)) + 1.0) / 2.0},
{name: "circ out/in", fn: t => (t < 0.5) ? 0.5 * Math.sqrt(1.0 - (t = t * 2.0 - 1.0) * t) : -0.5 * ((Math.sqrt(1.0 - (t = t * 2.0 - 1.0) * t) - 1.0) - 1.0)},

{name: "cube in", fn: t => t * t * t},
{name: "cube out", fn: t => 1.0 + (--t) * t * t},
{name: "cube in/out", fn: t => t <= 0.5 ? t * t * t * 4.0 : 1.0 + (--t) * t * t * 4.0},
{name: "cube out/in", fn: t =>  0.5 * ((t = t * 2.0 - 1.0) * t * t + 1.0)},

{name: "quart in", fn: t => t * t * t * t},
{name: "quart out", fn: t => 1.0 - (--t) * t * t * t},
{name: "quart in/out", fn: t => t <= 0.5 ? t * t * t * t * 8.0 : (1.0 - (t = t * 2.0 - 2.0) * t * t * t) * 0.5 + 0.5},
{name: "quart out/in", fn: t => (t < 0.5) ? -0.5 * (t = t * 2.0 - 1.0) * t * t * t + 0.5 : 0.5 * (t = t * 2.0 - 1.0) * t * t * t + 0.5},

{name: "quint in", fn: t => t * t * t * t * t},
{name: "quint out", fn: t => (t = t - 1) * t * t * t * t + 1.0},
{name: "quint in/out", fn: t => ((t *= 2.0) < 1.0) ? (t * t * t * t * t) / 2.0 : ((t -= 2.0) * t * t * t * t + 2.0) / 2.0},
{name: "quint out/in", fn: t => 0.5 * ((t = t * 2.0 - 1.0) * t * t * t * t + 1.0)},

{name: "expo in", fn: t => Math.pow(2, 10.0 * (t - 1.0))},
{name: "expo out", fn: t => -Math.pow(2, -10.0 * t) + 1.0},
{name: "expo in/out", fn: t => t < .5 ? Math.pow(2, 10.0 * (t * 2.0 - 1.0)) / 2.0 : (-Math.pow(2, -10.0 * (t * 2.0 - 1.0)) + 2.0) / 2.0},
{name: "expo out/in", fn: t => (t < 0.5) ? 0.5 * (1.0 - Math.pow(2, -20.0 * t)) : (t == 0.5) ?  0.5 :  0.5 * (Math.pow(2, 20.0 * (t - 1.0)) + 1.0)},

{name: "back in", fn: t => t * t * (5.0 * t - 4.0)},
{name: "back out", fn: t => 1 - --t * t * (-5.0 * t - 4.0)},
{name: "back in/out", fn: t => { t *= 2.0
if (t < 1.0) return t * t * (5.0 * t - 4.0) / 2.0
t -= 2.0
return (1 - t * t * (-5.0 * t - 4.0)) / 2.0 + 0.5
}},

{name: "elastic in", fn: t => {const ELASTIC_AMPLITUDE=1, ELASTIC_PERIOD=0.4; return -(ELASTIC_AMPLITUDE * Math.pow(2, 10 * (t -= 1)) * Math.sin((t - (ELASTIC_PERIOD / (Math.PI / 2) * Math.asin(1 / ELASTIC_AMPLITUDE))) * (Math.PI * 2) / ELASTIC_PERIOD))}},
{name: "elastic out", fn: t => {const ELASTIC_AMPLITUDE=1, ELASTIC_PERIOD=0.4; return  (ELASTIC_AMPLITUDE * Math.pow(2, -10 * t) * Math.sin((t - (ELASTIC_PERIOD / (Math.PI * 2) * Math.asin(1 / ELASTIC_AMPLITUDE))) * (Math.PI * 2) / ELASTIC_PERIOD) +1)}},
{name: "elastic in/out", fn: t => {const ELASTIC_AMPLITUDE=1, ELASTIC_PERIOD=0.4; if (t < 0.5) return -0.5 * (Math.pow(2, 10.0 * (t -= 0.5)) * Math.sin((t - (ELASTIC_PERIOD / 4.0)) * (Math.PI * 2) / ELASTIC_PERIOD));
return Math.pow(2, -10 * (t -= 0.5)) * Math.sin((t - (ELASTIC_PERIOD / 4)) * (Math.PI * 2.0) / ELASTIC_PERIOD) * 0.5 + 1.0;}},

{name: "steps", fn: t => Math.floor(t * 10.0) / 10.0},
{name: "array", fn: t => [0.0, 0.4, 0.7, 0.2, 1.0][Math.floor(t * 5.0)]},
{name: "randomish", fn: t => t + -0.03 + Math.random() * 0.06}
][idx];
}

```