90% of the time you can see some sort of face 😱 Press 'Compile & Run' to generate new one.
Fork from Metaball Contour Lines by @reinder
#contourlines
Log in to post a comment.
// Forked from "contourline" by reinder
// https://turtletoy.net/turtle/104c4775c5
const turtle = new Turtle();
const part = (x=0,y=0) => [x+rnd(15), y+rnd(15), (.5+Math.random()*1.5)*100];
const parts = [part(-50,-50), part(50,-50), part(0, 20), part(0,50), part(-30,60), part(30,60), part(-15,70), part(15,70)];
const zFunc = p => parts.reduce((a, c) => a+c[2]/(1+Math.sqrt((c[0]-p[0])**2+(c[1]-p[1])**2)), 0);
function walk(i) {
const lines = ContourLines(i, 15/(1+i), zFunc);
lines.forEach((line,idx) => {
const r = i/10;
const s = i % 3 == 0 ? 8 : (i % 3 == 1 ? 4 : 2);
turtle.jump(snap(line[0][0] + rnd(r),s), snap(line[0][1] + rnd(r),s));
turtle.goto(snap(line[1][0] + rnd(r),s), snap(line[1][1] + rnd(r),s));
});
return i < 20;
}
function rnd(r) { return -r + Math.random() * r*2; }
function snap(v, snap=1) {return ((v/snap)|0)*snap; }
////////////////////////////////////////////////////////////////
// Contour Lines utility code. Created by Reinder Nijhoff 2020
// https://turtletoy.net/turtle/104c4775c5
////////////////////////////////////////////////////////////////
function ContourLines(z, step, zFunc) {
const intersectSegmentZ = (z, v1, v2) => {
if (v1[2] == v2[2]) return false;
const t = (z - v1[2]) / (v2[2] - v1[2]);
if (t < 0 || t > 1) return false;
return [v1[0]+(v2[0]-v1[0])*t, v1[1]+(v2[1]-v1[1])*t];
}
const intersectTriangleZ = (z, p1, p2, p3) => {
const v1 = intersectSegmentZ(z, p1, p2);
const v2 = intersectSegmentZ(z, p2, p3);
if (v1 && v2) return [v1, v2];
const v3 = intersectSegmentZ(z, p3, p1);
if (v1 && v3) return [v1, v3];
if (v2 && v3) return [v2, v3];
return false;
}
const result = [];
for (let x = -100; x <= 100; x += step) {
for (let y = -100; y <= 100; y += step) {
const corners = [[x, y], [x+step, y], [x+step, y+step], [x, y+step]];
corners.forEach( c => c[2] = zFunc(c) );
const c3 = [x+step/2, y+step/2, zFunc([x+step/2, y+step/2])];
corners.forEach( (c, i) => {
const pair = intersectTriangleZ(z, c, corners[(i+1) & 3], c3);
if (pair) {
result.push(pair);
}
});
}
}
return result;
}