terrain_forge/algorithms/
fractal.rs1use crate::{Algorithm, Grid, Rng, Tile};
2
3#[derive(Debug, Clone)]
4pub struct FractalConfig {
5 pub fractal_type: String,
7 pub max_iterations: usize,
8}
9
10impl Default for FractalConfig {
11 fn default() -> Self {
12 Self {
13 fractal_type: "mandelbrot".to_string(),
14 max_iterations: 100,
15 }
16 }
17}
18
19pub struct Fractal {
20 config: FractalConfig,
21}
22
23impl Fractal {
24 pub fn new(config: FractalConfig) -> Self {
25 Self { config }
26 }
27}
28
29impl Default for Fractal {
30 fn default() -> Self {
31 Self::new(FractalConfig::default())
32 }
33}
34
35impl Algorithm<Tile> for Fractal {
36 fn generate(&self, grid: &mut Grid<Tile>, seed: u64) {
37 let mut rng = Rng::new(seed);
38 if self.config.fractal_type == "mandelbrot" {
39 generate_mandelbrot(grid, self.config.max_iterations);
40 } else if self.config.fractal_type == "julia" {
41 generate_julia(grid, &mut rng, self.config.max_iterations);
42 } else {
43 panic!("Unknown fractal type: {}", self.config.fractal_type);
44 }
45 }
46
47 fn name(&self) -> &'static str {
48 "Fractal"
49 }
50}
51
52fn generate_mandelbrot(grid: &mut Grid<Tile>, max_iter: usize) {
53 let (w, h) = (grid.width(), grid.height());
54
55 for y in 0..h {
56 for x in 0..w {
57 let cx = (x as f64 / w as f64 - 0.5) * 4.0 - 0.5;
58 let cy = (y as f64 / h as f64 - 0.5) * 4.0;
59
60 let mut zx = 0.0;
61 let mut zy = 0.0;
62 let mut iter = 0;
63
64 while zx * zx + zy * zy < 4.0 && iter < max_iter {
65 let temp = zx * zx - zy * zy + cx;
66 zy = 2.0 * zx * zy + cy;
67 zx = temp;
68 iter += 1;
69 }
70
71 if iter < max_iter / 3 {
72 grid.set(x as i32, y as i32, Tile::Floor);
73 }
74 }
75 }
76}
77
78fn generate_julia(grid: &mut Grid<Tile>, rng: &mut Rng, max_iter: usize) {
79 let (w, h) = (grid.width(), grid.height());
80 let cx = rng.random() * 1.6 - 0.8;
82 let cy = rng.random() * 1.6 - 0.8;
83
84 for y in 0..h {
85 for x in 0..w {
86 let mut zx = (x as f64 / w as f64 - 0.5) * 3.0;
87 let mut zy = (y as f64 / h as f64 - 0.5) * 3.0;
88 let mut iter = 0;
89
90 while zx * zx + zy * zy < 4.0 && iter < max_iter {
91 let temp = zx * zx - zy * zy + cx;
92 zy = 2.0 * zx * zy + cy;
93 zx = temp;
94 iter += 1;
95 }
96
97 if iter < max_iter / 2 {
98 grid.set(x as i32, y as i32, Tile::Floor);
99 }
100 }
101 }
102}