-
Notifications
You must be signed in to change notification settings - Fork 53
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
Added the arc method to turtle with two examples #189
Changes from all commits
File filter
Filter by extension
Conversations
Jump to
Diff view
Diff view
There are no files selected for viewing
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,43 @@ | ||
extern crate turtle; | ||
use turtle::{Point, Turtle}; | ||
|
||
fn main() { | ||
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. I think your |
||
let mut turtle = Turtle::new(); | ||
let init_pos: Point = turtle.position(); | ||
|
||
let _radius_outer = 250.0; | ||
turtle.set_pen_color("#fe0000"); | ||
turtle.pen_up(); | ||
turtle.go_to((init_pos.x - (_radius_outer), init_pos.y)); | ||
turtle.pen_down(); | ||
turtle.set_fill_color("#fe0000"); | ||
turtle.begin_fill(); | ||
turtle.arc(_radius_outer, None, None); | ||
turtle.end_fill(); | ||
|
||
let _radius_mid = 115.0; | ||
turtle.pen_up(); | ||
turtle.go_to((init_pos.x.round() - (_radius_mid), init_pos.y)); | ||
turtle.pen_down(); | ||
turtle.set_fill_color("white"); | ||
turtle.set_pen_color("white"); | ||
turtle.begin_fill(); | ||
turtle.arc(_radius_mid, None, None); | ||
turtle.end_fill(); | ||
|
||
let _radius_inner = 60.0; | ||
turtle.pen_up(); | ||
turtle.go_to((init_pos.x - (_radius_inner), init_pos.y)); | ||
turtle.pen_down(); | ||
turtle.set_fill_color("#fe0000"); | ||
turtle.begin_fill(); | ||
turtle.arc(_radius_inner, None, None); | ||
turtle.end_fill(); | ||
|
||
let _size = 25.0; | ||
turtle.pen_up(); | ||
turtle.go_to((init_pos.x - (_radius_mid) + _size - 2.0, init_pos.y)); | ||
turtle.pen_down(); | ||
turtle.set_pen_size(_size); | ||
turtle.forward(250.0); | ||
} |
Original file line number | Diff line number | Diff line change | ||||
---|---|---|---|---|---|---|
@@ -0,0 +1,29 @@ | ||||||
extern crate turtle; | ||||||
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more.
Suggested change
|
||||||
use turtle::Turtle; | ||||||
|
||||||
enum Turn { | ||||||
Left, | ||||||
Right, | ||||||
} | ||||||
|
||||||
// Shameless copy from https://gist.github.com/fogleman/006e4069348fa163b8ae | ||||||
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more.
Suggested change
Let's move this comment to the top of the file. |
||||||
|
||||||
fn turn(i: i64) -> Turn { | ||||||
let left = (((i & -i) << 1) & i) != 0; | ||||||
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. I know you didn't create this method of drawing this picture, so this suggestion is optional: Could you try to explain this line a bit and why it works? Maybe link to an explanation if one can be found online. |
||||||
if left { | ||||||
return Turn::Left; | ||||||
} else { | ||||||
return Turn::Right; | ||||||
} | ||||||
} | ||||||
|
||||||
fn main() { | ||||||
let mut turtle = Turtle::new(); | ||||||
turtle.set_speed("instant"); | ||||||
for i in 1..100000 { | ||||||
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. Looks like the image is getting cut off at the current window size. We should consider shifting the whole drawing up a bit (using |
||||||
match turn(i) { | ||||||
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. I wonder if we could avoid some unnecessary complexity by moving the body of fn main() {
let mut turtle = Turtle::new();
turtle.set_speed("instant");
for i in 1i64..100000 {
let should_turn_left = (((i & -i) << 1) & i) != 0;
if should_turn_left {
turtle.arc(-4.0, Some(90.0), Some(36))
} else {
turtle.arc(4.0, Some(90.0), Some(36)),
}
}
} This avoids the |
||||||
Turn::Left => turtle.arc(-4.0, Some(90.0), Some(36)), | ||||||
Turn::Right => turtle.arc(4.0, Some(90.0), Some(36)), | ||||||
} | ||||||
} | ||||||
} |
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -1,11 +1,12 @@ | ||
use std::f64::consts::PI; | ||
use std::fmt::Debug; | ||
|
||
use tokio::time; | ||
|
||
use crate::radians::{self, Radians}; | ||
use crate::ipc_protocol::{ProtocolClient, RotationDirection}; | ||
use crate::radians::{self, Radians}; | ||
use crate::renderer_server::TurtleId; | ||
use crate::{Turtle, Color, Point, Speed}; | ||
use crate::{Color, Point, Speed, Turtle}; | ||
|
||
/// Any distance value (positive or negative) | ||
pub type Distance = f64; | ||
|
@@ -58,8 +59,7 @@ impl AsyncTurtle { | |
// of many programs that use the turtle crate. | ||
crate::start(); | ||
|
||
let client = ProtocolClient::new().await | ||
.expect("unable to create renderer client"); | ||
let client = ProtocolClient::new().await.expect("unable to create renderer client"); | ||
Self::with_client(client).await | ||
} | ||
|
||
|
@@ -68,7 +68,7 @@ impl AsyncTurtle { | |
let id = client.create_turtle().await; | ||
let angle_unit = AngleUnit::Degrees; | ||
|
||
Self {client, id, angle_unit} | ||
Self { client, id, angle_unit } | ||
} | ||
|
||
pub async fn forward(&mut self, distance: Distance) { | ||
|
@@ -87,7 +87,9 @@ impl AsyncTurtle { | |
|
||
pub async fn left(&mut self, angle: Angle) { | ||
let angle = self.angle_unit.to_radians(angle); | ||
self.client.rotate_in_place(self.id, angle, RotationDirection::Counterclockwise).await | ||
self.client | ||
.rotate_in_place(self.id, angle, RotationDirection::Counterclockwise) | ||
.await | ||
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. It looks like you have rustfmt running in your editor. Could you please remove all the changes that aren't relevant to the PR? |
||
} | ||
|
||
pub async fn wait(&mut self, secs: f64) { | ||
|
@@ -101,6 +103,27 @@ impl AsyncTurtle { | |
time::delay_for(time::Duration::from_millis((secs * 1000.0) as u64)).await | ||
} | ||
|
||
pub async fn arc(&mut self, radius: Distance, extent: Option<Angle>, steps: Option<i32>) { | ||
let angle = extent.unwrap_or(360.0); | ||
|
||
// Arc Length = radius * angle in radians | ||
let angle_rad = 2.0 * PI * angle.abs() / 360.0; | ||
let arc_length = radius.abs() * angle_rad; | ||
|
||
let step_count = steps.unwrap_or(((arc_length / 4.0).round() + 1.0) as i32); | ||
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. Could you add a comment to explain this code? (I realize that it's taken from #100, so just do the best you can) |
||
let step_length = arc_length / step_count as f64; | ||
let step_angle = angle / step_count as f64; | ||
|
||
for _ in 0..step_count { | ||
self.forward(step_length).await; | ||
if radius < 0.0 { | ||
self.left(step_angle).await; | ||
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. We have to be careful using |
||
} else { | ||
self.right(step_angle).await; | ||
} | ||
} | ||
} | ||
|
||
pub fn into_sync(self) -> Turtle { | ||
self.into() | ||
} | ||
|
@@ -122,13 +145,13 @@ impl AsyncTurtle { | |
} | ||
|
||
pub async fn set_x(&mut self, x: f64) { | ||
let Point {x: _, y} = self.position().await; | ||
self.go_to(Point {x, y}).await | ||
let Point { x: _, y } = self.position().await; | ||
self.go_to(Point { x, y }).await | ||
} | ||
|
||
pub async fn set_y(&mut self, y: f64) { | ||
let Point {x, y: _} = self.position().await; | ||
self.go_to(Point {x, y}).await | ||
let Point { x, y: _ } = self.position().await; | ||
self.go_to(Point { x, y }).await | ||
} | ||
|
||
pub async fn home(&mut self) { | ||
|
@@ -155,7 +178,9 @@ impl AsyncTurtle { | |
// Formula from: https://stackoverflow.com/a/24234924/551904 | ||
let angle = angle - radians::TWO_PI * ((angle + radians::PI) / radians::TWO_PI).floor(); | ||
|
||
self.client.rotate_in_place(self.id, angle, RotationDirection::Counterclockwise).await | ||
self.client | ||
.rotate_in_place(self.id, angle, RotationDirection::Counterclockwise) | ||
.await | ||
} | ||
|
||
pub fn is_using_degrees(&self) -> bool { | ||
|
@@ -291,13 +316,15 @@ impl AsyncTurtle { | |
angle | ||
}; | ||
|
||
self.client.rotate_in_place(self.id, angle, RotationDirection::Counterclockwise).await | ||
self.client | ||
.rotate_in_place(self.id, angle, RotationDirection::Counterclockwise) | ||
.await | ||
} | ||
|
||
pub async fn wait_for_click(&mut self) { | ||
use crate::{ | ||
event::{MouseButton::LeftButton, PressedState::Pressed}, | ||
Event::MouseButton, | ||
event::{PressedState::Pressed, MouseButton::LeftButton}, | ||
}; | ||
|
||
loop { | ||
|
Original file line number | Diff line number | Diff line change | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|
@@ -1,8 +1,8 @@ | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
use std::fmt::Debug; | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
|
||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
use crate::{Color, Point, Speed, Distance, Angle}; | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
use crate::async_turtle::AsyncTurtle; | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
use crate::sync_runtime::block_on; | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
use crate::{Angle, Color, Distance, Point, Speed}; | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
|
||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
/// A turtle with a pen attached to its tail | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
/// | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
|
@@ -26,7 +26,7 @@ impl Default for Turtle { | |||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
|
||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
impl From<AsyncTurtle> for Turtle { | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
fn from(turtle: AsyncTurtle) -> Self { | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
Self {turtle} | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
Self { turtle } | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
} | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
} | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
|
||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
|
@@ -199,6 +199,46 @@ impl Turtle { | |||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
block_on(self.turtle.wait(secs)) | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
} | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
|
||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
/// Instructs the turtle to draw an arc by the given angle for a given radius in the given step count from the current position of the turtle. | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more.
Suggested change
Updated based on the docs for the circle function in the Python turtle module |
||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
/// | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
/// The `radius` parameter is a floation point number that represents the radius of the arc | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
/// that you want to draw. If a negative `radius` is passed its absolute value is | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
/// considered for drawing the arc. | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
Comment on lines
+204
to
+206
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more.
Suggested change
Fixed a typo and rewording a bit. Are we sure that we should be taking the absolute value of the radius? The Python
|
||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
/// | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
/// The `extent` parameter is a floating point number that represents how much you want the | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
/// turtle to rotate. If the `extent` parameter is `None` then it is defaulted to 360. If | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
/// a negative `extent` is passed the arc is drawn in the opposite direction. | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
Comment on lines
+208
to
+210
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more.
Suggested change
Instead of specifying |
||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
/// | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
/// the `steps` parameter is an integer that represent over how many steps you want the turtle to draw. If the `steps` parameter | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
/// is `None` then it is defaulted to the arc_length / 4.0. | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
Comment on lines
+212
to
+213
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more.
Suggested change
We don't want to commit to how we're calculating the steps, so I modified this line to be a bit more vague. |
||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
/// | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
/// #Example | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more.
Suggested change
nit: whitespace |
||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
/// | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
/// ```rust | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more.
Suggested change
Since there are no assertions in this example, it can probably be marked as |
||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
/// # use turtle::*; | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
/// # let mut turtle = Turtle::new(); | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
/// // Turtle will draw an arc of 90 in a clockwise direction | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
/// turtle.arc(100.0, Some(90.0), None); | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
/// | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
/// // Turtle will draw an arc of 90 in a anti-clockwise direction | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
/// turtle.arc(-100.0, Some(90.0), None); | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
/// | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
/// // Turtle will draw an arc of 90 in a clockwise direction | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
/// turtle.arc(-100.0, Some(-90.0), None); | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
/// | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
/// //Turtle will draw an arc of 90 in a anti-clockwise direction | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
/// turtle.arc(-100.0, Some(90.0), None); | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
/// | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
/// // Turtle will draw an arc of 90 in a clockwise direction in 10 steps | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
/// turtle.arc(100.0, Some(90.0), Some(10)); | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
/// | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
/// // Turtle will draw an arc of 90 in a clockwise direction in 100 steps | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
/// turtle.arc(100.0, Some(90.0), Some(100)); | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
Comment on lines
+220
to
+236
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more.
Suggested change
When using an example to try to teach the subtleties of an API to someone, it's good to group related statements together so readers can see which small differences lead to the same outcome. I've changed this example to group some of the lines you added together so the user can see how the signs of the radius and extent affect the output. Note: If your other documentation about us taking the absolute value of the radius is true, are these examples even accurate? I think this should be fine once we fix the code to no longer take the absolute value. We should definitely make sure we're accurate about the behaviour of our code in our examples! |
||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
/// ``` | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
pub fn arc(&mut self, radius: Distance, extent: Option<Angle>, steps: Option<i32>) { | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more.
Suggested change
Let's make this method unstable for now. I am still questioning whether we should use |
||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
block_on(self.turtle.arc(radius, extent, steps)) | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
} | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
|
||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
pub(crate) fn into_async(self) -> AsyncTurtle { | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
self.turtle | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
} | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
|
@@ -964,7 +1004,9 @@ mod tests { | |||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
} | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
|
||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
#[test] | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
#[should_panic(expected = "Invalid color: Color { red: NaN, green: 0.0, blue: 0.0, alpha: 0.0 }. See the color module documentation for more information.")] | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
#[should_panic( | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
expected = "Invalid color: Color { red: NaN, green: 0.0, blue: 0.0, alpha: 0.0 }. See the color module documentation for more information." | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
)] | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
fn rejects_invalid_pen_color() { | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
let mut turtle = Turtle::new(); | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
turtle.set_pen_color(Color { | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
|
@@ -976,7 +1018,9 @@ mod tests { | |||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
} | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
|
||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
#[test] | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
#[should_panic(expected = "Invalid color: Color { red: NaN, green: 0.0, blue: 0.0, alpha: 0.0 }. See the color module documentation for more information.")] | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
#[should_panic( | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
expected = "Invalid color: Color { red: NaN, green: 0.0, blue: 0.0, alpha: 0.0 }. See the color module documentation for more information." | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
)] | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
fn rejects_invalid_fill_color() { | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
let mut turtle = Turtle::new(); | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
turtle.set_fill_color(Color { | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
|
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
extern crate
is no longer necessary in the Rust 2018 edition.