From dbf46ef01bbcabe3e97f2d878a4503c7277af70b Mon Sep 17 00:00:00 2001 From: Sameer Date: Sun, 21 Apr 2019 09:34:04 -0500 Subject: [PATCH] Add new images --- README.md | 26 +++++- out/arrowhead.svg | 2 +- out/crystal.svg | 6 ++ out/dragon.svg | 2 +- out/gosper.svg | 6 ++ out/hilbert.svg | 6 ++ out/koch.svg | 2 +- out/kolam.svg | 6 ++ out/moore.svg | 6 ++ out/plant.svg | 6 ++ out/sierpinski.svg | 2 +- out/sierpinski_carpet.svg | 6 ++ out/snowflake.svg | 6 ++ src/main.rs | 187 ++++++++++++++++++++++++++++++++++---- 14 files changed, 246 insertions(+), 23 deletions(-) create mode 100644 out/crystal.svg create mode 100644 out/gosper.svg create mode 100644 out/hilbert.svg create mode 100644 out/kolam.svg create mode 100644 out/moore.svg create mode 100644 out/plant.svg create mode 100644 out/sierpinski_carpet.svg create mode 100644 out/snowflake.svg diff --git a/README.md b/README.md index 603deec..45940e6 100644 --- a/README.md +++ b/README.md @@ -1,6 +1,6 @@ # L-systems in Rust -Renderings of various L-systems using Rust and Cairo. +Renderings of various L-systems using Rust and Cairo. Special thanks goes to [Paul Bourke](http://paulbourke.net/fractals/lsys/) and the [L-systems Wikipedia page](https://en.wikipedia.org/wiki/L-system) for the systems below ## Sierpinski Triangle ![sierpinski](out/sierpinski.svg) @@ -13,3 +13,27 @@ Renderings of various L-systems using Rust and Cairo. ## Dragon Curve ![dragon](out/dragon.svg) + +## Fractal Plant (Wikipedia) +![plant](out/plant.svg) + +## Moore Curve +![moore](out/moore.svg) + +## Hilbert Curve +![hilbert](out/hilbert.svg) + +## Sierpinski Carpet +![sierpinski_capret](out/sierpinski_carpet.svg) + +## Koch Snowflake +![snowflake](out/snowflake.svg) + +## Hexagonal Gosper +![gosper](out/gosper.svg) + +## Kolam +![kolam](out/kolam.svg) + +## Crystal +![crystal](out/crystal.svg) diff --git a/out/arrowhead.svg b/out/arrowhead.svg index faaf7c0..5e79d1f 100644 --- a/out/arrowhead.svg +++ b/out/arrowhead.svg @@ -1,6 +1,6 @@ - + diff --git a/out/crystal.svg b/out/crystal.svg new file mode 100644 index 0000000..13960ea --- /dev/null +++ b/out/crystal.svg @@ -0,0 +1,6 @@ + + + + + + diff --git a/out/dragon.svg b/out/dragon.svg index 2f824c1..880de08 100644 --- a/out/dragon.svg +++ b/out/dragon.svg @@ -1,6 +1,6 @@ - + diff --git a/out/gosper.svg b/out/gosper.svg new file mode 100644 index 0000000..84ebcc6 --- /dev/null +++ b/out/gosper.svg @@ -0,0 +1,6 @@ + + + + + + diff --git a/out/hilbert.svg b/out/hilbert.svg new file mode 100644 index 0000000..0869210 --- /dev/null +++ b/out/hilbert.svg @@ -0,0 +1,6 @@ + + + + + + diff --git a/out/koch.svg b/out/koch.svg index 2da1c7e..7fbe123 100644 --- a/out/koch.svg +++ b/out/koch.svg @@ -1,6 +1,6 @@ - + diff --git a/out/kolam.svg b/out/kolam.svg new file mode 100644 index 0000000..de9af84 --- /dev/null +++ b/out/kolam.svg @@ -0,0 +1,6 @@ + + + + + + diff --git a/out/moore.svg b/out/moore.svg new file mode 100644 index 0000000..5d72be4 --- /dev/null +++ b/out/moore.svg @@ -0,0 +1,6 @@ + + + + + + diff --git a/out/plant.svg b/out/plant.svg new file mode 100644 index 0000000..ae89372 --- /dev/null +++ b/out/plant.svg @@ -0,0 +1,6 @@ + + + + + + diff --git a/out/sierpinski.svg b/out/sierpinski.svg index f0ed46e..3ca0101 100644 --- a/out/sierpinski.svg +++ b/out/sierpinski.svg @@ -1,6 +1,6 @@ - + diff --git a/out/sierpinski_carpet.svg b/out/sierpinski_carpet.svg new file mode 100644 index 0000000..d5e7fa5 --- /dev/null +++ b/out/sierpinski_carpet.svg @@ -0,0 +1,6 @@ + + + + + + diff --git a/out/snowflake.svg b/out/snowflake.svg new file mode 100644 index 0000000..c33a866 --- /dev/null +++ b/out/snowflake.svg @@ -0,0 +1,6 @@ + + + + + + diff --git a/src/main.rs b/src/main.rs index 8a1ad64..1232fbe 100644 --- a/src/main.rs +++ b/src/main.rs @@ -9,10 +9,18 @@ fn main() { sierpinski(); arrowhead(); dragon(); + plant(); + moore(); + hilbert(); + sierpinski_carpet(); + snowflake(); + gosper(); + kolam(); + crystal(); } fn koch() { - let mut out = File::create("koch.svg").unwrap(); + let mut out = File::create("out/koch.svg").unwrap(); run( "F", &['F'], @@ -27,7 +35,7 @@ fn koch() { } fn sierpinski() { - let mut out = File::create("sierpinski.svg").unwrap(); + let mut out = File::create("out/sierpinski.svg").unwrap(); run( "F-G-G", &['F', 'G'], @@ -43,7 +51,7 @@ fn sierpinski() { } fn arrowhead() { - let mut out = File::create("arrowhead.svg").unwrap(); + let mut out = File::create("out/arrowhead.svg").unwrap(); run( "A", &['A', 'B'], @@ -53,13 +61,13 @@ fn arrowhead() { other => vec![other], }, std::f64::consts::PI * 1. / 3., - 4, + 6, &mut out, ); } fn dragon() { - let mut out = File::create("dragon.svg").unwrap(); + let mut out = File::create("out/dragon.svg").unwrap(); run( "FX", &['F'], @@ -69,13 +77,146 @@ fn dragon() { other => vec![other], }, std::f64::consts::PI / 2., - 10, + 12, + &mut out, + ); +} + +fn plant() { + let mut out = File::create("out/plant.svg").unwrap(); + run( + "X", + &['F'], + |c: char| match c { + 'X' => "F-[[X]+X]+F[+FX]-X".chars().collect(), + 'F' => "FF".chars().collect(), + other => vec![other], + }, + std::f64::consts::PI * 25.0 / 180.0, + 5, + &mut out, + ); +} + +fn moore() { + let mut out = File::create("out/moore.svg").unwrap(); + run( + "LFL+F+LFL", + &['F'], + |c: char| match c { + 'L' => "-RF+LFL+FR-".chars().collect(), + 'R' => "+LF-RFR-FL+".chars().collect(), + other => vec![other], + }, + std::f64::consts::PI * 90.0 / 180.0, + 5, &mut out, ); } -fn run(axiom: &str, variables: &[char], rules: F, angle: f64, iterations: usize, writer: W) -where +fn hilbert() { + let mut out = File::create("out/hilbert.svg").unwrap(); + run( + "A", + &['F'], + |c: char| match c { + 'A' => "-BF+AFA+FB-".chars().collect(), + 'B' => "+AF-BFB-FA+".chars().collect(), + other => vec![other], + }, + std::f64::consts::PI / 2.0, + 6, + &mut out, + ); +} + +fn sierpinski_carpet() { + let mut out = File::create("out/sierpinski_carpet.svg").unwrap(); + run( + "F+F+F+F", + &['F'], + |c: char| match c { + 'F' => "FF+F+F+F+FF".chars().collect(), + other => vec![other], + }, + std::f64::consts::PI / 2., + 4, + &mut out, + ); +} + +fn snowflake() { + let mut out = File::create("out/snowflake.svg").unwrap(); + run( + "F++F++F", + &['F'], + |c: char| match c { + 'F' => "F-F++F-F".chars().collect(), + other => vec![other], + }, + std::f64::consts::PI / 3., + 4, + &mut out, + ); +} + +fn gosper() { + let mut out = File::create("out/gosper.svg").unwrap(); + run( + "XF", + &['F'], + |c: char| match c { + 'X' => "X+YF++YF-FX--FXFX-YF+".chars().collect(), + 'Y' => "-FX+YFYF++YF+FX--FX-Y".chars().collect(), + other => vec![other], + }, + std::f64::consts::PI / 3., + 4, + &mut out, + ); +} + +fn kolam() { + let mut out = File::create("out/kolam.svg").unwrap(); + run( + "-D--D", + &['F'], + |c: char| match c { + 'A' => "F++FFFF--F--FFFF++F++FFFF--F".chars().collect(), + 'B' => "F--FFFF++F++FFFF--F--FFFF++F".chars().collect(), + 'C' => "BFA--BFA".chars().collect(), + 'D' => "CFC--CFC".chars().collect(), + other => vec![other], + }, + std::f64::consts::PI / 4.0, + 6, + &mut out, + ); +} + +fn crystal() { + let mut out = File::create("out/crystal.svg").unwrap(); + run( + "F+F+F+F", + &['F'], + |c: char| match c { + 'F' => "FF+F++F+F".chars().collect(), + other => vec![other], + }, + std::f64::consts::PI / 2., + 4, + &mut out, + ); +} + +fn run( + axiom: &str, + variables_to_draw: &[char], + rules: F, + angle: f64, + iterations: usize, + writer: W, +) where F: Fn(char) -> Vec + Copy, W: Write, { @@ -94,26 +235,36 @@ where // let segment_count = state.chars().filter(|c| variables.contains(&c)).count(); - - ctx.move_to(0.0, 0.5); + ctx.move_to(0.5, 0.5); + let mut stack: Vec<((f64, f64), f64)> = vec![]; + let mut curangle = -std::f64::consts::PI / 2.0; for c in state.chars() { match c { '+' => { - ctx.rotate(-angle); + // ctx.rotate(angle); + curangle += angle; } '-' => { - ctx.rotate(angle); + // ctx.rotate(-angle); + curangle -= angle; + } + '|' => { + curangle = -curangle; + } + '[' => { + stack.push((ctx.get_current_point(), curangle)); + } + ']' => { + let state = stack.pop().unwrap(); + ctx.move_to((state.0).0, (state.0).1); + curangle = state.1; } other => { - if variables.contains(&other) { - ctx.rel_line_to(0.01, 0.0); + if variables_to_draw.contains(&other) { + ctx.rel_line_to(0.005 * f64::cos(curangle), 0.005 * f64::sin(curangle)); } } } } ctx.stroke(); - - // let mut fout = File::create("out.png").unwrap(); - // surf.write_all(&mut fout).unwrap(); - // println!("{}", axiom); }