Prompt utilise pour regenerer cette page :
Page: L-Systems & Fractals - Lindenmayer System Visualization
Description: "Where simple rules unfold into infinite complexity"
Icon: "tree"
Tags: fractal, generative, turtle-graphics
Status: validated
=== FILE STRUCTURE ===
Files in this page directory:
- index.md (front matter + main HTML with preset info display)
- _controls.right.md (weight: 20) - Preset selector, iterations slider, Draw/Grow buttons
- _algorithm.after.md (no weight) - Algorithm explanation
- default.js - Main L-System JavaScript (IIFE, no imports)
- default.scss - All page styles
- 11 preset JS files (_preset-*.js) that register on window.LSYSTEM_PRESETS
=== INDEX.MD ===
Front matter:
title: "L-Systems & Fractals"
description: "Where simple rules unfold into infinite complexity"
icon: "tree"
tags: ["fractal", "generative", "turtle-graphics"]
status: ["validated"]
Body HTML:
<section class="container visual size-800 ratio-1-1 canvas-contain">
<canvas id="lsystem-canvas"></canvas>
</section>
<section class="preset-info">
<dl>
<dt>Axiom</dt><dd id="preset-axiom"><code>-</code></dd>
<dt>Rules</dt><dd id="preset-rules"><code>-</code></dd>
<dt>Angle</dt><dd id="preset-angle"><code>-</code></dd>
</dl>
</section>
Note: preset-info section shows current L-System definition below canvas (axiom, rules, angle).
=== WIDGET: _controls.right.md (weight: 20) ===
Title: "Controls"
Heading: ##### Preset
Contains <div class="lsystem-controls">:
1. <div class="control-group"> with <select id="preset-select"> having 4 optgroups:
Classic Fractals: Koch Snowflake (value="koch", selected), Sierpinski Triangle, Dragon Curve, Levy C Curve
Space-Filling: Hilbert Curve, Peano Curve, Gosper Curve
Plants: Binary Tree, Barnsley Fern, Plant
Geometric: Crystal
2. <div class="control-group"> with label "Iterations" and <div class="control-row"> containing:
<input type="range" id="iterations" min="1" max="12" value="4">
<span class="value" id="iterations-value">4</span>
3. <div class="lsystem-actions"> with 2 buttons:
- {{< button id="btn-draw" label="Draw" class="primary" >}}
- {{< button id="btn-grow" label="Grow" >}}
=== WIDGET: _algorithm.after.md ===
Title: "Algorithm"
Markdown content explaining:
- Lindenmayer Systems (formal grammars by Aristid Lindenmayer for modeling plant growth)
- Core Components: Axiom (seed string), Rules (production rules), Alphabet (F=forward, +=right, -=left, [=push, ]=pop)
- Turtle Graphics Interpretation (turtle position, angle, stack for branching)
- Famous L-Systems: Koch Snowflake, Sierpinski Triangle, Dragon Curve, Binary Tree, Fern
=== PRESET JS FILES (11 files) ===
Each file follows the pattern:
window.LSYSTEM_PRESETS = window.LSYSTEM_PRESETS || {};
window.LSYSTEM_PRESETS['key'] = { name, axiom, rules, angle, iterations, startAngle };
_preset-koch.js: Koch Snowflake
axiom: 'F--F--F', rules: { F: 'F+F--F+F' }, angle: 60, iterations: 4, startAngle: 0
_preset-sierpinski.js: Sierpinski Triangle
axiom: 'F-G-G', rules: { F: 'F-G+F+G-F', G: 'GG' }, angle: 120, iterations: 5, startAngle: 0
_preset-dragon.js: Dragon Curve
axiom: 'F', rules: { F: 'F+G', G: 'F-G' }, angle: 90, iterations: 10, startAngle: 0
_preset-levy.js: Levy C Curve
axiom: 'F', rules: { F: '+F--F+' }, angle: 45, iterations: 12, startAngle: 0
_preset-hilbert.js: Hilbert Curve
axiom: 'A', rules: { A: '-BF+AFA+FB-', B: '+AF-BFB-FA+' }, angle: 90, iterations: 5, startAngle: 0
_preset-peano.js: Peano Curve
axiom: 'F', rules: { F: 'F+F-F-F-F+F+F+F-F' }, angle: 90, iterations: 3, startAngle: 0
_preset-gosper.js: Gosper Curve (Flowsnake)
axiom: 'F', rules: { F: 'F-G--G+F++FF+G-', G: '+F-GG--G-F++F+G' }, angle: 60, iterations: 4, startAngle: 0
_preset-tree.js: Binary Tree
axiom: 'X', rules: { F: 'FF', X: 'F[+X][-X]FX' }, angle: 25, iterations: 6, startAngle: -90
_preset-fern.js: Barnsley Fern
axiom: 'X', rules: { X: 'F+[[X]-X]-F[-FX]+X', F: 'FF' }, angle: 25, iterations: 5, startAngle: -90
_preset-plant.js: Plant
axiom: 'X', rules: { X: 'F-[[X]+X]+F[+FX]-X', F: 'FF' }, angle: 22.5, iterations: 5, startAngle: -90
_preset-crystal.js: Crystal
axiom: 'F+F+F+F', rules: { F: 'FF+F++F+F' }, angle: 90, iterations: 4, startAngle: 0
=== JAVASCRIPT: default.js ===
IIFE pattern, 'use strict', no external imports.
Author: Cylian
State variables:
PRESETS={} (loaded from window.LSYSTEM_PRESETS at init)
canvas, ctx, dpr
currentPreset='koch', iterations=4
isAnimating=false, animationId=null, segments=[], segmentIndex=0, animationSpeed=50
isGrowing=false, growIteration=0, growTimeoutId=null, GROW_DELAY_MS=800
cachedColors { background, primary, text }
Functions - L-System Engine:
- generateLSystem(axiom, rules, iterations): string rewriting loop. For each iteration,
iterates over each character, replaces with rules[char] or keeps original. Returns final string.
- interpretTurtle(lsystem, segmentLength, angleStep, startAngle):
Turtle graphics interpreter. Converts angle params to radians. Maintains x, y, angle, depth.
Commands: F/G = draw forward (creates segment {x1,y1,x2,y2,depth}), + = turn right (+angleRad),
- = turn left (-angleRad), [ = push state to stack (depth++), ] = pop state from stack.
After generation, sets maxDepth on all segments. Returns segments array.
- getBoundingBox(segments): returns { minX, minY, maxX, maxY, width, height }
- getDepthColor(depth, maxDepth): HSL gradient hue=120+(depth/maxDepth)*160 (green to violet),
saturation=70%, lightness=45%
Functions - Rendering:
- cacheColors(): reads --background-color-surface, --draw-color-primary, --text-color-surface
- initCanvas(): 800px fixed, DPR scaling via setTransform(dpr,0,0,dpr,0,0)
- getWidth()/getHeight(): canvas.width/height / dpr
- generate(): generates L-System, interprets turtle with calculated segment length
(baseLength=min(w,h)*0.6 * 0.5^iterations), computes bounding box, scales and centers
segments to fit canvas with 40px padding. Then draws immediately or starts animation.
- draw(maxIndex): clears canvas with background, draws segments 0..maxIndex with depth-based
HSL colors, lineWidth 1.5, lineCap round
- startAnimation(): resets segmentIndex=0, begins animateStep RAF loop
- animateStep(): increments segmentIndex by animationSpeed, draws, continues via RAF until complete
- stopAnimation(): cancelAnimationFrame
Functions - Grow Animation:
- generateAtIteration(iter): generates L-System at specific iteration, uses fixed segmentLength=10,
independently scales to fill canvas (own bounding box, 40px padding, centered). Updates iterations-value display.
- startGrow(): stops other animations, sets isGrowing=true, starts from iteration 0
- growStep(): calls generateAtIteration(current), advances iteration, schedules next with setTimeout(GROW_DELAY_MS=800ms)
- stopGrow(): clears timeout, removes .is-active from btn-grow, restores iteration display
Functions - Controls:
- updatePresetInfo(): updates #preset-axiom (innerHTML with <code>), #preset-rules (rules formatted as
"key -> value" joined by <br> in code tags), #preset-angle (degrees in code tag)
- initControls(): binds preset-select change (updates currentPreset, resets iterations to preset default,
updates slider+display, calls updatePresetInfo+generate), iterations input (updates var+display, generates),
btn-draw click (calls generate), btn-grow click (calls startGrow)
- reset(): stopAnimation + stopGrow, then generate
- toggleAnimation(): toggles isAnimating flag and .is-active on btn-animate
Functions - Init:
- init(): loads PRESETS from window.LSYSTEM_PRESETS, gets canvas, cacheColors, listens for
prefers-color-scheme change (recache + redraw), initCanvas, initControls, updatePresetInfo, generate
- Auto-init: DOMContentLoaded or immediate if ready
=== SCSS: default.scss ===
$breakpoint-s: 767px
Sections:
1. Layout (layout-main main):
flex column center, padding 2rem, gap 1.5rem
#lsystem-canvas: 100% w/h, 1px solid --draw-color-surface border, 4px radius, --background-color-surface bg
2. Controls (.lsystem-controls):
flex column, gap 1rem
.control-group: flex column, gap 0.25rem
label: 0.75rem font, weight 600, uppercase, --text-color-surface, letter-spacing 0.05em
select + input[type="range"]: width 100%
select: 0.5rem padding, 0.875rem font, themed colors, 4px radius, hover/focus changes border to primary
input[type="range"]: 6px height, accent-color primary, 16px thumb
.value: 0.875rem, weight 600, primary color, right-aligned
.control-row: flex row nowrap, center-aligned, gap 0.5rem
3. Actions (.lsystem-actions):
flex row wrap, gap 0.5rem, margin-top 0.5rem
.button: flex 1, min-width 80px
4. Responsive (max-width $breakpoint-s):
.lsystem-controls .control-group select: padding 0.75rem
Page entierement generee et maintenue par IA, sans intervention humaine.