Last one in this series.
Log in to post a comment.
// Forked from "Wandering again" by llemarie // https://turtletoy.net/turtle/c80c6ac104 // LL 2021 Canvas.setpenopacity(1); const density = 0.08; // min=0.01 max=2 step=0.01 const steps = 1000; // min=100 max=10000 step=1 const epicenters = 2; // min=1 max=10 step=1 const round = 0.; // min=-1 max=1 step=0.01 const turn = 2.0; // min=0 max=10 step=0.1 const wobble = 0; // min=0 max=1 step=1 (No,Yes) const draw_collision = 0; // min=0 max=1 step=1 (No,Yes) const canvas_size = 110; let grid; const grid_size = 50; const turtle = new Turtle(); let current_points; function walk(i) { if (i==0) { initGrid(); current_points = []; for (var j=0; j<epicenters; j++) { const cx = (Math.random() - 0.5) * canvas_size * 2; const cy = (Math.random() - 0.5) * canvas_size * 2; const ca = (Math.random() - 0.5) * Math.PI * 2; current_points.push(new Point(cx, cy, density, ca)); } current_points.forEach(p => addToGrid(p)); } else if ((((i % 1000) == 0) && (current_points.length < 100)) || current_points.length < 10) { var gi = Math.floor(Math.random() * (grid_size**2)); var retries = grid_size ** 2; while (grid[gi].length < 1 && retries-- > 0) gi = (gi + 1) % (grid_size**2); if (grid[gi].length < 1) { const cx = (Math.random() - 0.5) * canvas_size * 2; const cy = (Math.random() - 0.5) * canvas_size * 2; const ca = (Math.random() - 0.5) * Math.PI * 2; current_points.push(new Point(cx, cy, density, ca)); } else { const ri = Math.floor(Math.random() * grid[gi].length); const point = grid[gi][ri]; r = point.r; a = point.a + Math.PI * ((Math.random()<0.5) ? -1 : 1) / (turn ? turn : (Math.random())); x = point.x; y = point.y; new_point = new Point(x, y, r, a); current_points.push(new_point); } } if (i >= steps * 100) return false; if (current_points.length < 1) return true; const ci = Math.floor(Math.random() * current_points.length); var r = current_points[ci].r; var a = current_points[ci].a + round / 10 * ((Math.random()<0.5) && wobble ? -1 : 1); //(Math.random() - 0.5) * 1; var dx = (current_points[ci].r + r) * 2 * Math.cos(a) var dy = (current_points[ci].r + r) * 2 * Math.sin(a) var x = current_points[ci].x + dx; var y = current_points[ci].y + dy; var new_point = new Point(x, y, r, a); var need_to_draw = true; if (!new_point.checkBounds() || new_point.checkCollision()) { if (draw_collision) draw(current_points[ci], new_point); current_points.splice(ci, 1); return true; } addToGrid(new_point); if (need_to_draw) { draw(current_points[ci], new_point); // sleep(1); } current_points[ci] = new_point; return true; } function draw(p1, p2) { turtle.jump(p1.x, p1.y); turtle.goto(p2.x, p2.y); } function initGrid() { grid = Array.from({length:grid_size**2}, (_) => []); } function getGridCell(point) { const gx = Math.min(grid_size-1, Math.max(0, Math.floor((point.x + canvas_size) / canvas_size / 2 * grid_size))); const gy = Math.min(grid_size-1, Math.max(0, Math.floor((point.y + canvas_size) / canvas_size / 2 * grid_size))); return gx + gy * grid_size; } function addToGrid(point) { if (point.checkCollision()) return; const gi = getGridCell(point); grid[gi].push(point); } class Point { constructor(x, y, r, a) { this.x = x; this.y = y; this.r = r; this.a = a; } checkBounds() { return (Math.abs(this.x - this.r) < canvas_size) && (Math.abs(this.y - this.r) < canvas_size); } checkCollision() { const gi = getGridCell(this); for (var dy=-1; dy<=1; dy++) { for (var dx=-1; dx<=1; dx++) { const gdi = gi + dx + dy * grid_size; if (gdi >= 0 && gdi < grid_size * grid_size) { for (var i=0, l=grid[gdi].length; i<l; i++) { const point = grid[gdi][i]; const dist2 = ((point.x - this.x) * (point.x - this.x) + (point.y - this.y) * (point.y - this.y)) / 8; if (dist2 < this.r * this.r) return true; } } } } const m_x = this.x / m_scale - offset_x; const m_y = this.y / m_scale - offset_y; const m = mandelbrot(m_x, m_y) / max_iterations; if (m < 0.6) return true; // const d = Math.hypot(this.x, this.y); // if (d > 90 || d < 40) return true; return false; } } function sleep(ms) { const start = Date.now(); while (Date.now() - start < ms); } const max_iterations = 25 /// min = 1, max = 100, step = 1 const m_scale = 87 /// min = 10, max = 1000, step = 0.01 const offset_x = 0.6 /// min = -10, max = 10, step = 0.001 const offset_y = 0 /// min = -10, max = 10, step = 0.001 function mandelbrot(x, y) { var cr = x, ci = y, zr = 0, zi = 0, iterations = 0; while (zr * zr + zi * zi < 4) { const new_zr = zr * zr - zi * zi + cr; const new_zi = 2 * zr * zi + ci; zr = new_zr; zi = new_zi; iterations += 1; if (iterations >= max_iterations) break; } return iterations; }