I saw segaldigital implementation (reddit.com/r/plotter…_dots_some_hexagons/) of Leon Rische's blogpost leonrische.me/pages/generative_art_with_cfgs.html and I thought... nice!
Hexogonal Tree ⬡ (variation)
Hexogonal Tree ⬡ (variation)
Log in to post a comment.
const length = 15; // min=1 max=100 step=1 const lengthRatio = .5; // min=0 max=1 step=.1 const thickness = 5; // min=1 max=10 step=1 const thicknessRatio = .6 // min=0 max=1 step=.1 const generationLimit = 4 // min=1 max=20 step=1 const iterationLimit = 30 // min=1 max=30 step=1 const invForkProbPerGen = .70 // min=.50 max=1 step=.001 const invForkProbPerIter = .87 // min=.50 max=1 step=.01 const circleProb = .1 //min=0 max=.5 step=.01 // You can find the Turtle API reference here: https://turtletoy.net/syntax Canvas.setpenopacity(.8); const forkProbPerGen = 1 - invForkProbPerGen; const forkProbPerIter = 1 - invForkProbPerIter; // Global code will be evaluated once. class Fork { constructor(branches, state, iteration, generation) { this.state = state; this.iteration = iteration | 0; this.generation = generation | 0; this.branches = branches; } generate(t) { this.state.restore(t); if(this.generation < generationLimit) { let gts = new TurtleState(t); gts.thickness *= thicknessRatio; (new Fork(3, gts, 0, this.generation + 1)).generate(t); } let bLength = length * Math.pow(lengthRatio, this.generation); this.state.restore(t); if(Math.random() < circleProb) { t.seth(270); let circleDivisions = 3; t.jump(t.x() - ((bLength * .25) / circleDivisions), t.y()); for(let d = 1; d < 4; d++) { let show = Math.random() < .5; let start = ((bLength * .25) / circleDivisions) * d; let max = ((bLength * .25) / circleDivisions) * (d + 1); for(let r = start; r < max; r += .25) { t.jump(t.x() -.25, t.y()); if(show) { t.circle(r); } } } this.state.restore(t); } this.state.restore(t); t.left(60); let ts = new TurtleState(t); let forks = []; for(let i = 0; i < this.branches; i++) { if(this.iteration < iterationLimit && Math.random() > (forkProbPerGen * this.generation) + (forkProbPerIter * this.iteration)) { t.forward(bLength); forks.push(new Fork(2, new TurtleState(t), this.iteration + 1, this.generation)); } ts.restore(t); t.right(120); ts.store(t); } forks.forEach(function(f) { if(f.iteration < 7) { f.generate(t); } }); } } class TurtleState { constructor(...args) { this.store(...args); } store(turtle, x, y, isdown, thickness) { this.h = turtle; this.x = x; this.y = y; this.isdown = isdown; this.thickness = thickness if(x === undefined) { this.h = turtle.h(); this.x = turtle.x(); this.y = turtle.y(); this.isdown = turtle.isdown(); this.thickness = turtle.thickness; } } restore(turtle) { turtle.seth(this.h); turtle.jump(this.x, this.y); this.isdown? turtle.down(): turtle.up(); turtle.thickness = this.thickness; } clone() { return new TurtleState(this.h, [this.x, this.y], this.isdown, this.thickness); } } // The walk function will be called until it returns false. function walk(i) { const turtle = new Slowbro(); turtle.thickness = thickness; const s = new TurtleState(turtle); let f = new Fork(3, s); f.generate(turtle); return false; turtle.forward(100); s.restore(turtle); turtle.right(144); s.save(turtle); return i < 4; } //////////////////////////////////////////////////////////////// // Slowbro utility code. Created by Lionel Lemarie 2021 // Based on Slowpoke, which removes most duplicate lines // Slowbro adds optional thickness to the lines //////////////////////////////////////////////////////////////// function Slowbro(x, y) { const linesDrawn = {}; class Slowbro extends Turtle { constructor(x, y) { super(x, y); this.thickness = 1; this.offset = 0.2; this.slowpoke_skip = this.slowpoke_draw = 0; } goto(x, y) { if (Array.isArray(x)) { y = x[1]; x = x[0]; } const ox = this.x(), oy = this.y(); if (this.isdown()) { const p = [x, y], o = [ox, oy]; const h1 = o[0].toFixed(2) + '_' + p[0].toFixed(2) + o[1].toFixed(2) + '_' + p[1].toFixed(2); const h2 = p[0].toFixed(2) + '_' + o[0].toFixed(2) + p[1].toFixed(2) + '_' + o[1].toFixed(2); if (linesDrawn[h1] || linesDrawn[h2]) { super.up(); super.goto(p); super.down(); this.slowpoke_skip++; return; } linesDrawn[h1] = linesDrawn[h2] = true; this.slowpoke_draw++; for (var dx = this.thickness-1; dx >=0 ; dx--) { for (var dy = this.thickness-1; dy >= 0; dy--) { if (!dx && !dy) continue; super.goto( x + dx * this.offset, y + dy * this.offset); super.goto(ox + dx * this.offset, oy + dy * this.offset); } } } super.goto(x, y); } } return new Slowbro(x, y); }