diff --git a/imgs/circle.png b/imgs/circle.png new file mode 100644 index 0000000..a0d9618 Binary files /dev/null and b/imgs/circle.png differ diff --git a/imgs/square.png b/imgs/square.png new file mode 100644 index 0000000..8eb356f Binary files /dev/null and b/imgs/square.png differ diff --git a/output.png b/output.png index e8381c9..91684fd 100644 Binary files a/output.png and b/output.png differ diff --git a/src/main.rs b/src/main.rs index 92edce2..d8f458f 100644 --- a/src/main.rs +++ b/src/main.rs @@ -1,19 +1,45 @@ mod turtle; -use turtle::Turtle; +use turtle::{defaults, Turtle}; -fn square(turtle: &mut turtle::Turtle) { - turtle.left(90.0); - turtle.forward(5); +#[allow(dead_code)] +fn square() { + let mut turtle = Turtle::new(); + let default_pos = defaults::position(); + let steps_count = 20; + + turtle.set_pos(( + default_pos.0 - (turtle.step_length() * steps_count / 2) as i32, + default_pos.1 + (turtle.step_length() * steps_count / 2) as i32 + )); + + turtle.left_forward(90.0, steps_count); for _ in 0..3 { - turtle.right(90.0); - turtle.forward(5); + turtle.right_forward(90.0, steps_count); } + turtle.save("imgs/square.png").unwrap(); +} + +#[allow(dead_code)] +fn circle() { + let mut turtle = Turtle::new(); + let default_pos = defaults::position(); + + let circumference = (36 * 2 * defaults::STEP_LENGTH) as f64; + let radius = circumference / (2.0 * std::f64::consts::PI); + + turtle.set_pos(( + default_pos.0 - (turtle.step_length() * 2 / 2) as i32, + default_pos.1 - radius as i32 + )); + + for _ in 0..36 { + turtle.forward_right(2, 10.0); + } + turtle.save("imgs/circle.png").unwrap(); } fn main() { - let mut turtle = Turtle::new(); - - square(&mut turtle); - turtle.save("output.png").unwrap(); + square(); + circle(); } diff --git a/src/turtle.rs b/src/turtle.rs index f7edf83..0e05048 100644 --- a/src/turtle.rs +++ b/src/turtle.rs @@ -8,36 +8,50 @@ type ImgBufU8 = ImageBuffer, Vec>; type Colour = Rgb; type Coord = (i32, i32); -const DEFAULT_WIDTH: u32 = 300; -const DEFAULT_HEIGHT: u32 = 300; -const DEFAULT_BACKGROUND_COLOUR: Colour = Rgb([255u8, 255u8, 255u8]); -const DEFAULT_COLOUR: Colour = Rgb([0u8, 0u8, 0u8]); -const DEFAULT_POS: Coord = ((DEFAULT_WIDTH as f64/2.0) as i32, (DEFAULT_HEIGHT as f64/2.0) as i32); +pub mod defaults { + use super::{Colour, Coord, Rgb}; + + pub const WIDTH: u32 = 300; + pub const HEIGHT: u32 = 300; + pub const BACKGROUND_COLOUR: Colour = Rgb([255u8, 255u8, 255u8]); + pub const COLOUR: Colour = Rgb([0u8, 0u8, 0u8]); + pub const STEP_LENGTH: u32 = 10; + pub const ANGLE: f64 = 0.0; + + pub fn position() -> Coord { + ((WIDTH as f64 / 2.0) as i32, + (HEIGHT as f64 / 2.0) as i32) + } +} pub struct Turtle { buf: ImgBufU8, colour: Colour, pos: Coord, step_length: u32, - angle: f64, // угол в радианах + angle: f64, } impl Turtle { pub fn new() -> Self { - let mut buf = ImageBuffer::new(DEFAULT_WIDTH, DEFAULT_HEIGHT); + let mut buf = ImageBuffer::new(defaults::WIDTH, defaults::HEIGHT); for pixel in buf.pixels_mut() { - *pixel = DEFAULT_BACKGROUND_COLOUR; + *pixel = defaults::BACKGROUND_COLOUR; } Turtle { buf, - colour: DEFAULT_COLOUR, - pos: DEFAULT_POS, - step_length: 10, - angle: 0.0, + colour: defaults::COLOUR, + pos: defaults::position(), + step_length: defaults::STEP_LENGTH, + angle: defaults::ANGLE, } } + pub fn step_length(&self) -> u32 { + self.step_length + } + pub fn position(&self) -> Coord { self.pos } @@ -46,26 +60,55 @@ impl Turtle { self.angle.to_degrees() } + pub fn set_pos(&mut self, coord: Coord) { + self.pos.0 = coord.0; + self.pos.1 = coord.1; + } + + pub fn right(&mut self, degrees: f64) { + self.angle += degrees.to_radians(); + self.angle = self.angle.rem_euclid(2.0 * std::f64::consts::PI); + } + + pub fn right_forward(&mut self, degrees: f64, steps_count: u32) { + self.right(degrees); + self.forward(steps_count); + } + + pub fn forward_right(&mut self, steps_count: u32, degrees: f64) { + self.forward(steps_count); + self.right(degrees); + } + + pub fn left(&mut self, degrees: f64) { + self.angle -= degrees.to_radians(); + self.angle = self.angle.rem_euclid(2.0 * std::f64::consts::PI); + } + + pub fn left_forward(&mut self, degrees: f64, steps_count: u32) { + self.left(degrees); + self.forward(steps_count); + } + + pub fn forward_left(&mut self, steps_count: u32, degrees: f64) { + self.forward(steps_count); + self.left(degrees); + } + pub fn forward(&mut self, steps_count: u32) { let start_pos = self.pos; let dy = self.angle.sin() * steps_count as f64 * self.step_length as f64; let dx = self.angle.cos() * steps_count as f64 * self.step_length as f64; - self.pos.0 += dx.round() as i32; - self.pos.1 += dy.round() as i32; - + self.set_pos(( + self.pos.0 + dx.round() as i32, + self.pos.1 + dy.round() as i32 + )); + self.draw_line(start_pos, self.pos); } - pub fn right(&mut self, degrees: f64) { - self.angle += degrees.to_radians(); - } - - pub fn left(&mut self, degrees: f64) { - self.angle -= degrees.to_radians(); - } - pub fn save

(&self, output_path: P) -> ImageResult<()> where P: AsRef