### Flowers🌼

Generating some flowers

Interesting variant:
- Flowers🌼 (variation)

```const turtle = new Turtle();

const grid = 2; // min=1, max=7, step=1
const size = 7/8 * 200 / grid;
const flowerSize = 14 // min=5, max=50, step=1

let totalHatch = 100; // min=0, max=300, step=1
const innerSize = 0.9; // min=0, max=1, step=0.01

let totalLeaves = 7; // min=5, max=20, step=2
const leafSize = 3.2; // min=1, max=5, step=0.01
const leafDetail = 12; // min=5, max=75, step=1
const innerLeafLines = 1; // min=0.00, max=1, step=0.25

const getX = x => (grid%2==1) ? x - (grid*0.5|0) - 0.5 : x - (grid*0.5);
const getY = y => (grid%2==1) ? y - (grid*0.5|0) - 0.5 : y - (grid*0.5);

function walk(i) {
const x = getX(i % grid);
const y = getY(i / grid | 0);
flower([x * size + size*0.5, y*size + size*0.5], flowerSize);
return i < grid*grid-1;
}

function flower(pos, size) {
circle(pos,size);
if (innerSize != 1) circle(pos,size * innerSize);

const startAngle = Math.random() * Math.PI*2;

// hatch lines in between rings of cirlce
let hatchOverlap = 0.075;
for(let i=0;i<totalHatch;i++) {
const angle = startAngle + (i+0) / totalHatch * Math.PI*2;
const a = add2(pos, fromAngle(angle, size * (innerSize - hatchOverlap)));
const b = add2(pos, fromAngle(angle, size * (1 + hatchOverlap)));
a[0] += (-0.5 * Math.random()) * size * 0.1;
a[1] += (-0.5 * Math.random()) * size * 0.1;
b[0] += (-0.5 * Math.random()) * size * 0.1;
b[1] += (-0.5 * Math.random()) * size * 0.1;
turtle.jump(a);
turtle.goto(b);
}

// Dots in flower. based on "Voronoi Spiral" by Reinder https://turtletoy.net/turtle/70b4fd8c25
for (let i=0; i<300; i++) {
const ratio = 0.38196601125;
const r = 4 * Math.sqrt(i);
const a = i * 2 * Math.PI * ratio;
const x = Math.cos(a)*r;
const y = Math.sin(a)*r;
circle(add2(pos, [x*size*0.014*innerSize, y*size*0.014*innerSize]), size * 0.0185);
}

// make amount of leaves less precise on bigger grid
if (grid > 0 && totalLeaves > 6) {
totalLeaves += (-2+Math.random()*4) | 0;
}

// Draw leaves
for(let i=0;i<totalLeaves;i++) {
const angle1 = startAngle + (i+0) / totalLeaves * Math.PI*2;
const leafAngle = startAngle + (i+0.5) / totalLeaves * Math.PI*2;
const angle2 = startAngle + (i+1) / totalLeaves * Math.PI*2;

const pos1 = add2(pos, fromAngle(angle1, size));
const pos2 = add2(pos, fromAngle(angle2, size));
const leafStart = add2(pos, fromAngle(leafAngle, size));
const leafTip = add2(pos, fromAngle(leafAngle, size * leafSize));

const r2 = Math.random();
const r3 =Math.random();

turtle.jump(pos1);
for (let l=0;l<leafDetail;l++) {
const t = l/(leafDetail-1);
let tx = (1-t)*0.5;
const p = lerpPath(pos1, leafTip, t, tx); // TODO
turtle.goto(p);
}

turtle.jump(leafTip);
for (let l=0;l<leafDetail;l++) {
const t = l/(leafDetail-1);
let tx = pingpong((1-t)*0.25)*r2;
tx = t*0.5;
const p = lerpPath(leafTip, pos2 , t, tx);
turtle.goto(p);
}

// inner leaf line 1
turtle.jump(leafStart);
for (let l=0;l<leafDetail * innerLeafLines;l++) {
const t = l/(leafDetail-1);
let tx = t*0.25*r3;
const p = lerpPath(leafStart, leafTip, t, tx);
turtle.goto(p);
}

// inner leaf line 2
turtle.jump(leafStart);
for (let l=0;l<leafDetail * innerLeafLines;l++) {
const t = l/(leafDetail-1);
let tx = pingpong(t/15)*r3;
const p = lerpPath(leafStart, leafTip, t, tx);
turtle.goto(p);
}
}
}

function circle(pos, r = 1, segments = 20) {
const {x, y} = pos;
for(let i = 0; i <= segments; i++) {
const angle = i/segments * Math.PI*2;
const p = add2(pos, fromAngle(angle, r));
if (i === 0) turtle.jump(p);
else turtle.goto(p);
}
}

function lerpPath(a,b, t, t2) {
const diff = sub2(b,a);
const randomize = 0.04; // min=0, max=0.1, step=0.001
let tt = pingpong(randomized(t, randomize)) * t2;
return add2(lerp2(a, b, t), scl([-diff[1], diff[0]], tt));
}

const scl = (a,s) => [a[0]*s, a[1]*s];
const scl2 = (a,b) => [a[0]*b[0], a[1]*b[1]];
const add2 = (a,b) => [a[0]+b[0], a[1]+b[1]];
const sub2 = (a,b) => [a[0]-b[0], a[1]-b[1]];
const dot2 = (a,b) => a[0]*b[0] + a[1]*b[1];
const atan2 = a => Math.atan2(-a[1],a[0]);
const len2 = a => Math.sqrt(a[0]*a[0]+a[1]*a[1]);
const nrm2 = a => scl(a, 1/len2(a));
const fromAngle = (a,r = 1.0) => [Math.sin(a)*r, Math.cos(a)*r];
const clamp = (v, a, b) => Math.min(b, Math.max(a, v));
const clamp01 = v => clamp(v, 0, 1);
const pingpong = t => (t < 0.5 ? t : 1-t) * 2;
const randomized = (t, range = 0.1) => t + -range + Math.random() * (range*2);
const mod2 = v => (v%2==0) ? v%1 : 1-((v-0.5)%1)
const lerp = (a,b,t) => a+(b-a)*t;
const lerp2 = (a,b,tx, ty=tx) => [lerp(a[0],b[0],tx), lerp(a[1],b[1],ty)];
```