Sierpinski square curve: Difference between revisions
Content added Content deleted
m (Minor edit) |
(Added Rust solution) |
||
Line 367: | Line 367: | ||
);</lang> |
);</lang> |
||
See: [https://github.com/thundergnat/rc/blob/master/img/sierpinski-square-curve-perl6.svg Sierpinski-square-curve-perl6.svg] (offsite SVG image) |
See: [https://github.com/thundergnat/rc/blob/master/img/sierpinski-square-curve-perl6.svg Sierpinski-square-curve-perl6.svg] (offsite SVG image) |
||
=={{header|Rust}}== |
|||
Program output is a file in SVG format. |
|||
<lang rust>// [dependencies] |
|||
// svg = "0.8.0" |
|||
use svg::node::element::path::Data; |
|||
use svg::node::element::Path; |
|||
struct SierpinskiSquareCurve { |
|||
current_x : f64, |
|||
current_y : f64, |
|||
current_angle : i32, |
|||
line_length : f64 |
|||
} |
|||
impl SierpinskiSquareCurve { |
|||
fn new(x : f64, y : f64, length : f64, angle : i32) -> SierpinskiSquareCurve { |
|||
SierpinskiSquareCurve { |
|||
current_x : x, |
|||
current_y : y, |
|||
current_angle : angle, |
|||
line_length : length |
|||
} |
|||
} |
|||
fn rewrite(order : usize) -> String { |
|||
let mut str = String::from("F+XF+F+XF"); |
|||
for _ in 0..order { |
|||
let mut tmp = String::new(); |
|||
for ch in str.chars() { |
|||
match ch { |
|||
'X' => tmp.push_str("XF-F+F-XF+F+XF-F+F-X"), |
|||
_ => tmp.push(ch) |
|||
} |
|||
} |
|||
str = tmp; |
|||
} |
|||
str |
|||
} |
|||
fn execute(&mut self, order : usize) -> Path { |
|||
let mut data = Data::new().move_to((self.current_x, self.current_y)); |
|||
for ch in SierpinskiSquareCurve::rewrite(order).chars() { |
|||
match ch { |
|||
'F' => data = self.draw_line(data), |
|||
'+' => self.turn(90), |
|||
'-' => self.turn(-90), |
|||
_ => {} |
|||
} |
|||
} |
|||
Path::new() |
|||
.set("fill", "none") |
|||
.set("stroke", "black") |
|||
.set("stroke-width", "1") |
|||
.set("d", data) |
|||
} |
|||
fn draw_line(&mut self, data : Data) -> Data { |
|||
use std::f64::consts::PI; |
|||
let theta = (PI * self.current_angle as f64) / 180.0; |
|||
self.current_x += self.line_length * theta.cos(); |
|||
self.current_y -= self.line_length * theta.sin(); |
|||
data.line_to((self.current_x, self.current_y)) |
|||
} |
|||
fn turn(&mut self, angle : i32) { |
|||
self.current_angle = (self.current_angle + angle) % 360; |
|||
} |
|||
fn save(file : &str, size : usize, order : usize) -> std::io::Result<()> { |
|||
use svg::node::element::Rectangle; |
|||
let x = 315.0; |
|||
let y = 630.0; |
|||
let rect = Rectangle::new() |
|||
.set("width", "100%") |
|||
.set("height", "100%") |
|||
.set("fill", "white"); |
|||
let mut hilbert = SierpinskiSquareCurve::new(x, y, 5.0, 0); |
|||
let document = svg::Document::new() |
|||
.set("width", size) |
|||
.set("height", size) |
|||
.add(rect) |
|||
.add(hilbert.execute(order)); |
|||
svg::save(file, &document) |
|||
} |
|||
} |
|||
fn main() { |
|||
SierpinskiSquareCurve::save("sierpinski_square_curve.svg", 635, 5).unwrap(); |
|||
}</lang> |
|||
=={{header|Sidef}}== |
=={{header|Sidef}}== |