Skip to content

Commit f4081a7

Browse files
Add gosper curve fractal
1 parent 9003f2a commit f4081a7

6 files changed

Lines changed: 73 additions & 14 deletions

File tree

README.md

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -28,7 +28,7 @@ françaises** dans `src/*.ml`.
2828
| Évasion | Mandelbrot, Julia, Burning Ship, Tricorn, Multibrot (n=3…8), Celtic, Buffalo, Perpendicular Burning Ship, Heart, Perpendicular Mandelbrot, Perpendicular Celtic, Duck, Buddhabrot |
2929
| Dynamique | Newton (z³−1), Phoenix, Lyapunov, Lyapunov multiséquence, Bassin de Newton généralisé, Orbitale de Nova, Collatz complexe, Attracteur de Clifford, Attracteur de Peter de Jong, Attracteur d'Ikeda, Attracteur de Hénon |
3030
| IFS | Barnsley (fougère), Sierpinski, Tapis de Sierpinski |
31-
| L-système | Koch (flocon de neige), Dragon de Heighway, Joint apollonien, Arbre de Pythagore |
31+
| L-système | Koch (flocon de neige), Dragon de Heighway, Courbe de Gosper, Joint apollonien, Arbre de Pythagore |
3232
| Magnétiques | Magnet I, Magnet II, Magnet III, Lambda (logistique complexe), Lambda cubique, Magnet cosinus, Magnet sinus, Nova magnétique |
3333

3434
---

public/js/renderer.js

Lines changed: 26 additions & 8 deletions
Original file line numberDiff line numberDiff line change
@@ -76,7 +76,7 @@ const VIEW_PRESETS = {
7676
lichtenberg_figures: { centerX: 0.0, centerY: 0.0, span: 3.8 },
7777
koch: { centerX: 0.45, centerY: -0.28, span: 0.9 },
7878
dragon_heighway: { centerX: 0.2, centerY: 0.0, span: 2.8 },
79-
dragon_curve: { centerX: 0.2, centerY: 0.0, span: 2.8 },
79+
gosper_curve: { centerX: 0.15, centerY: 0.05, span: 3.2 },
8080
cantor_set: { centerX: 0.0, centerY: 0.0, span: 2.6 },
8181
triangle_de_cercles_recursifs: { centerX: 0.0, centerY: 0.05, span: 2.4 },
8282
apollonian_gasket: { centerX: 0.0, centerY: 0.0, span: 2.2 },
@@ -104,7 +104,7 @@ function getMultibrotPreset(power) {
104104
}
105105

106106
const POINT_FRACTALS = new Set(["barnsley", "sierpinski", "tapis_sierpinski", "menger_sponge", "mandelbulb", "tetraedre_sierpinski", "julia_quaternion", "mandelbox", "vicsek_fractal", "lichtenberg_figures", "attracteur_de_clifford", "attracteur_de_peter_de_jong", "attracteur_ikeda", "attracteur_de_henon", "lorenz_attractor", "feigenbaum_tree"]);
107-
const LINE_FRACTALS = new Set(["koch", "dragon_heighway", "dragon_curve", "cantor_set", "triangle_de_cercles_recursifs", "apollonian_gasket", "t_square_fractal", "h_fractal", "hilbert_curve", "peano_curve", "arbre_pythagore"]);
107+
const LINE_FRACTALS = new Set(["koch", "dragon_heighway", "gosper_curve", "cantor_set", "triangle_de_cercles_recursifs", "apollonian_gasket", "t_square_fractal", "h_fractal", "hilbert_curve", "peano_curve", "arbre_pythagore"]);
108108

109109
/** Fonctions fractales exportées par WASM */
110110
// Les fractales 3D en JS pur (julia_quaternion, mandelbox) sont toujours disponibles.
@@ -322,7 +322,7 @@ const FRACTAL_FAMILIES = [
322322
fractales: [
323323
["koch", "Koch"],
324324
["dragon_heighway", "Dragon de Heighway"],
325-
["dragon_curve", "Courbe du dragon"],
325+
["gosper_curve", "Courbe de Gosper"],
326326
["cantor_set", "Ensemble de Cantor"],
327327
["triangle_de_cercles_recursifs", "Triangle de cercles récursifs"],
328328
["apollonian_gasket", "Joint apollonien"],
@@ -1104,6 +1104,20 @@ function genererDragonHeighway(iterations) {
11041104
return s;
11051105
}
11061106

1107+
function genererGosper(iterations) {
1108+
let s = "A";
1109+
for (let i = 0; i < iterations; i++) {
1110+
let next = "";
1111+
for (const ch of s) {
1112+
if (ch === "A") next += "A-B--B+A++AA+B-";
1113+
else if (ch === "B") next += "+A-BB--B-A++A+B";
1114+
else next += ch;
1115+
}
1116+
s = next;
1117+
}
1118+
return s.replace(/[AB]/g, "F");
1119+
}
1120+
11071121
function genererHilbert(iterations) {
11081122
let s = "A";
11091123
for (let i = 0; i < iterations; i++) {
@@ -1526,10 +1540,14 @@ function dessinerFractaleLineaire(ctxCible, w, h, vueCible, renduParams) {
15261540
const n = Math.max(0, Math.min(6, Math.floor((renduParams.maxIter - 64) / 128)));
15271541
const commands = kochGenerate(n);
15281542
dessinerCommandeLineaireMonde(traceur, commands, 0.05, -0.28, 0.0, 0.8 / Math.pow(3, n), Math.PI / 3);
1529-
} else if (renduParams.fractal === "dragon_heighway" || renduParams.fractal === "dragon_curve") {
1543+
} else if (renduParams.fractal === "dragon_heighway") {
15301544
const n = Math.max(8, Math.min(15, Math.floor(renduParams.maxIter / 64) + 7));
15311545
const commands = genererDragonHeighway(n);
15321546
dessinerCommandeLineaireMonde(traceur, commands, -0.6, 0.0, 0.0, 1.7 / Math.pow(Math.SQRT2, n), Math.PI / 2);
1547+
} else if (renduParams.fractal === "gosper_curve") {
1548+
const n = Math.max(1, Math.min(4, Math.floor(renduParams.maxIter / 112) + 1));
1549+
const commands = genererGosper(n);
1550+
dessinerCommandeLineaireMonde(traceur, commands, -0.95, 0.35, 0.0, 2.2 / Math.pow(Math.sqrt(7), n), Math.PI / 3);
15331551
} else if (renduParams.fractal === "cantor_set") {
15341552
dessinerCantorMonde(traceur, renduParams.maxIter);
15351553
} else if (renduParams.fractal === "triangle_de_cercles_recursifs") {
@@ -1887,7 +1905,7 @@ async function loadWasm() {
18871905
mandelbox: typeof exports.mandelbox === "function" ? exports.mandelbox : mandelboxJS,
18881906
koch: typeof exports.koch === "function" ? exports.koch : null,
18891907
dragon_heighway: typeof exports.dragon_heighway === "function" ? exports.dragon_heighway : null,
1890-
dragon_curve: typeof exports.dragon_curve === "function" ? exports.dragon_curve : null,
1908+
gosper_curve: typeof exports.gosper_curve === "function" ? exports.gosper_curve : null,
18911909
cantor_set: typeof exports.cantor_set === "function" ? exports.cantor_set : null,
18921910
triangle_de_cercles_recursifs: typeof exports.triangle_de_cercles_recursifs === "function" ? exports.triangle_de_cercles_recursifs : null,
18931911
apollonian_gasket: typeof exports.apollonian_gasket === "function" ? exports.apollonian_gasket : null,
@@ -2636,7 +2654,7 @@ const FRACTAL_SOURCE_MAP = {
26362654
lichtenberg_figures: "fractales_ifs",
26372655
koch: "fractales_lsystem",
26382656
dragon_heighway: "fractales_lsystem",
2639-
dragon_curve: "fractales_lsystem",
2657+
gosper_curve: "fractales_lsystem",
26402658
cantor_set: "fractales_lsystem",
26412659
triangle_de_cercles_recursifs: "fractales_lsystem",
26422660
apollonian_gasket: "fractales_lsystem",
@@ -2757,7 +2775,7 @@ function highlightFrench(code) {
27572775
function applyFrenchTokens(line, kwRe) {
27582776
return line
27592777
.replace(kwRe, `<span class="kw">$1</span>`)
2760-
.replace(/\b(mandelbrot|mandelbrot_classe|julia|burning_ship|tricorn|multibrot|celtic|buffalo|perpendicular_burning_ship|heart|perpendicular_mandelbrot|perpendicular_celtic|duck|buddhabrot|newton|phoenix|lyapunov|lyapunov_multisequence|bassin_newton_generalise|orbitale_de_nova|collatz_complexe|attracteur_de_clifford|attracteur_de_peter_de_jong|attracteur_ikeda|attracteur_de_henon|lorenz_attractor|feigenbaum_tree|barnsley|sierpinski|tapis_sierpinski|menger_sponge|mandelbulb|vicsek_fractal|lichtenberg_figures|koch|dragon_heighway|dragon_curve|cantor_set|triangle_de_cercles_recursifs|apollonian_gasket|t_square_fractal|h_fractal|hilbert_curve|peano_curve|arbre_pythagore|magnet1|magnet2|magnet3|lambda_fractale|lambda_cubique|magnet_cosinus|magnet_sinus|nova_magnetique|barnsley_etape|sierpinski_etape|menger_etape|vicsek_etape|projeter_menger_x|projeter_menger_y|projeter_lorenz_x|projeter_lorenz_y|etapeTapisSierpinski|etapeAttracteurClifford|etapeAttracteurPeterDeJong|etapeAttracteurIkeda|etapeAttracteurHenon|etapeLorenzAttractor|etapeMengerSponge|etapeVicsekFractal|etapeLichtenberg|etapeMandelbulb|projeterMengerSponge|projeterLorenzAttractor|projeterMandelbulb|koch_generer|genererDragonHeighway|genererHilbert|genererPeano|norme_carre|complexe_diviser_re|complexe_diviser_im|iterer|etape|racine_approx|abs_val|abs_dynamique|abs_koch|remplacer|regle|generer|sinus_dynamique|cosinus_dynamique|sinus_magnetique|cosinus_magnetique)\b/g, `<span class="fn">$1</span>`)
2778+
.replace(/\b(mandelbrot|mandelbrot_classe|julia|burning_ship|tricorn|multibrot|celtic|buffalo|perpendicular_burning_ship|heart|perpendicular_mandelbrot|perpendicular_celtic|duck|buddhabrot|newton|phoenix|lyapunov|lyapunov_multisequence|bassin_newton_generalise|orbitale_de_nova|collatz_complexe|attracteur_de_clifford|attracteur_de_peter_de_jong|attracteur_ikeda|attracteur_de_henon|lorenz_attractor|feigenbaum_tree|barnsley|sierpinski|tapis_sierpinski|menger_sponge|mandelbulb|vicsek_fractal|lichtenberg_figures|koch|dragon_heighway|gosper_curve|cantor_set|triangle_de_cercles_recursifs|apollonian_gasket|t_square_fractal|h_fractal|hilbert_curve|peano_curve|arbre_pythagore|magnet1|magnet2|magnet3|lambda_fractale|lambda_cubique|magnet_cosinus|magnet_sinus|nova_magnetique|barnsley_etape|sierpinski_etape|menger_etape|vicsek_etape|projeter_menger_x|projeter_menger_y|projeter_lorenz_x|projeter_lorenz_y|etapeTapisSierpinski|etapeAttracteurClifford|etapeAttracteurPeterDeJong|etapeAttracteurIkeda|etapeAttracteurHenon|etapeLorenzAttractor|etapeMengerSponge|etapeVicsekFractal|etapeLichtenberg|etapeMandelbulb|projeterMengerSponge|projeterLorenzAttractor|projeterMandelbulb|koch_generer|genererDragonHeighway|genererGosper|genererHilbert|genererPeano|norme_carre|complexe_diviser_re|complexe_diviser_im|iterer|etape|racine_approx|abs_val|abs_dynamique|abs_koch|remplacer|regle|generer|sinus_dynamique|cosinus_dynamique|sinus_magnetique|cosinus_magnetique)\b/g, `<span class="fn">$1</span>`)
27612779
.replace(/\b(\d+\.\d+|\d+)\b/g, `<span class="num">$1</span>`)
27622780
.replace(/\b(cx|cy|zx|zy|c_re|c_im|max_iter|x|y|iter|xtemp|ax|ay|x2|y2|fx|fy|dfx|dfy|denom|delta_x|delta_y|x_prec|y_prec|xtemp|ytemp|d1|d2|d3|d4|puissance|rn|angle|r|theta|nx|ny|a|b|niveau|echelle|dist|score|somme|exposant|parametre)\b/g, `<span class="param">$1</span>`);
27632781
}
@@ -2780,7 +2798,7 @@ function highlightPython(code) {
27802798
function applyPyTokens(line, kwRe) {
27812799
return line
27822800
.replace(kwRe, `<span class="kw">$1</span>`)
2783-
.replace(/\b(mandelbrot|mandelbrot_classe|julia|burning_ship|tricorn|multibrot|celtic|buffalo|perpendicular_burning_ship|heart|perpendicular_mandelbrot|perpendicular_celtic|duck|buddhabrot|newton|phoenix|lyapunov|lyapunov_multisequence|bassin_newton_generalise|orbitale_de_nova|collatz_complexe|attracteur_de_clifford|attracteur_de_peter_de_jong|attracteur_ikeda|attracteur_de_henon|lorenz_attractor|feigenbaum_tree|barnsley|sierpinski|tapis_sierpinski|menger_sponge|mandelbulb|vicsek_fractal|lichtenberg_figures|koch|dragon_heighway|dragon_curve|cantor_set|triangle_de_cercles_recursifs|apollonian_gasket|t_square_fractal|h_fractal|hilbert_curve|peano_curve|arbre_pythagore|magnet1|magnet2|magnet3|lambda_fractale|lambda_cubique|magnet_cosinus|magnet_sinus|nova_magnetique|barnsley_etape|sierpinski_etape|menger_etape|vicsek_etape|projeter_menger_x|projeter_menger_y|projeter_lorenz_x|projeter_lorenz_y|koch_generer|genererDragonHeighway|genererHilbert|genererPeano|norme_carre|complexe_diviser_re|complexe_diviser_im|iterer|etape|racine_approx|abs_val|remplacer|regle|generer|sinus_dynamique|cosinus_dynamique|sinus_magnetique|cosinus_magnetique)\b/g, `<span class="fn">$1</span>`)
2801+
.replace(/\b(mandelbrot|mandelbrot_classe|julia|burning_ship|tricorn|multibrot|celtic|buffalo|perpendicular_burning_ship|heart|perpendicular_mandelbrot|perpendicular_celtic|duck|buddhabrot|newton|phoenix|lyapunov|lyapunov_multisequence|bassin_newton_generalise|orbitale_de_nova|collatz_complexe|attracteur_de_clifford|attracteur_de_peter_de_jong|attracteur_ikeda|attracteur_de_henon|lorenz_attractor|feigenbaum_tree|barnsley|sierpinski|tapis_sierpinski|menger_sponge|mandelbulb|vicsek_fractal|lichtenberg_figures|koch|dragon_heighway|gosper_curve|cantor_set|triangle_de_cercles_recursifs|apollonian_gasket|t_square_fractal|h_fractal|hilbert_curve|peano_curve|arbre_pythagore|magnet1|magnet2|magnet3|lambda_fractale|lambda_cubique|magnet_cosinus|magnet_sinus|nova_magnetique|barnsley_etape|sierpinski_etape|menger_etape|vicsek_etape|projeter_menger_x|projeter_menger_y|projeter_lorenz_x|projeter_lorenz_y|koch_generer|genererDragonHeighway|genererGosper|genererHilbert|genererPeano|norme_carre|complexe_diviser_re|complexe_diviser_im|iterer|etape|racine_approx|abs_val|remplacer|regle|generer|sinus_dynamique|cosinus_dynamique|sinus_magnetique|cosinus_magnetique)\b/g, `<span class="fn">$1</span>`)
27842802
.replace(/\b(\d+\.\d+|\d+)\b/g, `<span class="num">$1</span>`)
27852803
.replace(/\b(cx|cy|zx|zy|c_re|c_im|max_iter|x|y|iter|xtemp|ax|ay|x2|y2|fx|fy|dfx|dfy|denom|delta_x|delta_y|x_prec|y_prec|xtemp|ytemp|d1|d2|d3|d4|puissance|rn|angle|r|theta|nx|ny|a|b|niveau|echelle|dist|score|somme|exposant|parametre)\b/g, `<span class="param">$1</span>`);
27862804
}

scripts/compile_wasm.ml

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -220,7 +220,7 @@ déf main():
220220
afficher(f" WAT ecrit : {SORTIE_WAT.relative_to(RACINE)}")
221221
afficher(f" WASM ecrit: {SORTIE_WASM.relative_to(RACINE)} ({longueur(octets_wasm):,} octets)")
222222
223-
soit exports_requises = ["mandelbrot", "julia", "burning_ship", "tricorn", "multibrot", "celtic", "buffalo", "perpendicular_burning_ship", "heart", "perpendicular_mandelbrot", "perpendicular_celtic", "duck", "buddhabrot", "newton", "phoenix", "lyapunov", "lyapunov_multisequence", "bassin_newton_generalise", "orbitale_de_nova", "collatz_complexe", "attracteur_de_clifford", "attracteur_de_peter_de_jong", "attracteur_ikeda", "attracteur_de_henon", "lorenz_attractor", "feigenbaum_tree", "barnsley", "sierpinski", "tapis_sierpinski", "menger_sponge", "mandelbulb", "tetraedre_sierpinski", "julia_quaternion", "mandelbox", "vicsek_fractal", "lichtenberg_figures", "koch", "dragon_heighway", "dragon_curve", "cantor_set", "triangle_de_cercles_recursifs", "apollonian_gasket", "t_square_fractal", "h_fractal", "hilbert_curve", "peano_curve", "arbre_pythagore", "magnet1", "magnet2", "magnet3", "lambda_fractale", "lambda_cubique", "magnet_cosinus", "magnet_sinus", "nova_magnetique", "interpoler_lineaire", "interpoler_logarithmique", "ajuster_iterations_export", "mandelbrot_classe"]
223+
soit exports_requises = ["mandelbrot", "julia", "burning_ship", "tricorn", "multibrot", "celtic", "buffalo", "perpendicular_burning_ship", "heart", "perpendicular_mandelbrot", "perpendicular_celtic", "duck", "buddhabrot", "newton", "phoenix", "lyapunov", "lyapunov_multisequence", "bassin_newton_generalise", "orbitale_de_nova", "collatz_complexe", "attracteur_de_clifford", "attracteur_de_peter_de_jong", "attracteur_ikeda", "attracteur_de_henon", "lorenz_attractor", "feigenbaum_tree", "barnsley", "sierpinski", "tapis_sierpinski", "menger_sponge", "mandelbulb", "tetraedre_sierpinski", "julia_quaternion", "mandelbox", "vicsek_fractal", "lichtenberg_figures", "koch", "dragon_heighway", "gosper_curve", "cantor_set", "triangle_de_cercles_recursifs", "apollonian_gasket", "t_square_fractal", "h_fractal", "hilbert_curve", "peano_curve", "arbre_pythagore", "magnet1", "magnet2", "magnet3", "lambda_fractale", "lambda_cubique", "magnet_cosinus", "magnet_sinus", "nova_magnetique", "interpoler_lineaire", "interpoler_logarithmique", "ajuster_iterations_export", "mandelbrot_classe"]
224224
valider_exports_wasm(octets_wasm, exports_requises)
225225
afficher(f" Exports valides: {', '.join(exports_requises)}")
226226

scripts/integration_checks.py

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -51,7 +51,7 @@
5151
"lichtenberg_figures",
5252
"koch",
5353
"dragon_heighway",
54-
"dragon_curve",
54+
"gosper_curve",
5555
"cantor_set",
5656
"triangle_de_cercles_recursifs",
5757
"apollonian_gasket",

src/fractales_lsystem.ml

Lines changed: 43 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -80,8 +80,49 @@ déf dragon_heighway(cx, cy, max_iter):
8080
retour 6.0
8181
retour score
8282

83-
déf dragon_curve(cx, cy, max_iter):
84-
retour dragon_heighway(cx, cy, max_iter)
83+
déf gosper_curve(cx, cy, max_iter):
84+
soit x = cx
85+
soit y = cy
86+
soit dist = abs_koch(x) + abs_koch(y)
87+
soit niveau = 0.0
88+
soit echelle = 1.0
89+
soit nmax = min_koch(max_iter, 9.0)
90+
soit racine7 = 2.64575131106
91+
soit cos60 = 0.5
92+
soit sin60 = 0.86602540378
93+
94+
tantque niveau < nmax:
95+
soit u = x * cos60 + y * sin60
96+
soit v = -x * sin60 + y * cos60
97+
soit d_hex = abs_koch(abs_koch(v) - 0.19 / echelle) + abs_koch(u) * 0.45
98+
soit d_diag = abs_koch(abs_koch(u - 0.22 / echelle) - 0.11 / echelle) + abs_koch(v) * 0.35
99+
si d_hex < dist:
100+
dist = d_hex
101+
si d_diag < dist:
102+
dist = d_diag
103+
104+
soit branche = niveau % 3.0
105+
soit nx = x * racine7
106+
soit ny = y * racine7
107+
si branche == 0.0:
108+
x = nx - 0.62
109+
y = ny - 0.16
110+
sinonsi branche == 1.0:
111+
x = nx * cos60 - ny * sin60 + 0.18
112+
y = nx * sin60 + ny * cos60 - 0.48
113+
sinon:
114+
x = nx * cos60 + ny * sin60 - 0.18
115+
y = -nx * sin60 + ny * cos60 + 0.48
116+
echelle = echelle * racine7
117+
niveau = niveau + 1.0
118+
119+
soit seuil = 0.028
120+
si dist < seuil:
121+
retour max_iter * 0.91
122+
soit score = max_iter * 0.9 - (dist / (seuil * 11.0)) * (max_iter * 0.9)
123+
si score < 6.0:
124+
retour 6.0
125+
retour score
85126

86127
déf cantor_set(cx, cy, max_iter):
87128
soit x = (cx + 1.0) * 0.5

src/main.ml

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -19,7 +19,7 @@ soit MODES_EVASION = ["mandelbrot", "julia", "burning_ship", "tricorn", "multibr
1919
soit MODES_DYNAMIQUE = ["newton", "phoenix", "lyapunov", "lyapunov_multisequence", "bassin_newton_generalise", "orbitale_de_nova", "collatz_complexe", "attracteur_de_clifford", "attracteur_de_peter_de_jong", "attracteur_ikeda", "attracteur_de_henon", "lorenz_attractor", "feigenbaum_tree"]
2020
soit MODES_IFS = ["barnsley", "sierpinski", "tapis_sierpinski", "menger_sponge", "mandelbulb", "vicsek_fractal", "lichtenberg_figures", "tetraedre_sierpinski", "julia_quaternion", "mandelbox"]
2121
soit MODES_3D = ["tetraedre_sierpinski", "julia_quaternion", "mandelbox"]
22-
soit MODES_LSYSTEM = ["koch", "dragon_heighway", "dragon_curve", "cantor_set", "triangle_de_cercles_recursifs", "apollonian_gasket", "t_square_fractal", "h_fractal", "hilbert_curve", "peano_curve", "arbre_pythagore"]
22+
soit MODES_LSYSTEM = ["koch", "dragon_heighway", "gosper_curve", "cantor_set", "triangle_de_cercles_recursifs", "apollonian_gasket", "t_square_fractal", "h_fractal", "hilbert_curve", "peano_curve", "arbre_pythagore"]
2323
soit MODES_MAGNETIQUE = ["magnet1", "magnet2", "magnet3", "lambda_fractale", "lambda_cubique", "magnet_cosinus", "magnet_sinus", "nova_magnetique"]
2424
soit MODES_CLASSES_COMPAT = ["mandelbrot_classe"]
2525
affirmer longueur(MODES_EVASION) == 13

0 commit comments

Comments
 (0)