From f94511515f570f903b74f1bc3e31e6022d5ed476 Mon Sep 17 00:00:00 2001 From: Piripant Date: Sat, 9 Dec 2017 19:51:13 +0100 Subject: [PATCH 1/4] Added comments and test --- src/turtle.rs | 34 +++++++++++++++++++++++++++++----- 1 file changed, 29 insertions(+), 5 deletions(-) diff --git a/src/turtle.rs b/src/turtle.rs index df0b5f74..9687ff7d 100644 --- a/src/turtle.rs +++ b/src/turtle.rs @@ -989,9 +989,6 @@ impl Turtle { /// /// If the coordinates are the same as the turtle's current position, no rotation takes place. /// Always rotates the least amount necessary in order to face the given point. - /// - /// ## UNSTABLE - /// This feature is currently unstable and completely buggy. Do not use it until it is fixed. pub fn turn_towards(&mut self, target: Point) { let target_x = target[0]; let target_y = target[1]; @@ -1000,19 +997,24 @@ impl Turtle { let x = position[0]; let y = position[1]; + // If the target is (approximately) on the turtle don't turn if (target_x - x).abs() < 0.1 && (target_y - y).abs() < 0.1 { return; } let heading = self.window.fetch_turtle().heading; + // Calculate the target angle to reach let angle = (target_y - y).atan2(target_x - x); let angle = Radians::from_radians_value(angle); + // Calculate how much turning will be needed (angle - heading) + // And clamp it make sure the turtle doesn't turn more than 360 degrees let angle = (angle - heading) % radians::TWO_PI; // Try to rotate as little as possible let angle = if angle.abs() > radians::PI { - // Using signum to deal with negative angles properly - angle.signum()*(radians::TWO_PI - angle.abs()) + // Use signum to make sure the angle has the right sign + // And the turtle turns the right way + -angle.signum()*(radians::TWO_PI - angle.abs()) } else { angle @@ -1156,4 +1158,26 @@ mod tests { assert_eq!(turtle.position()[1].round(), 100.0); assert_eq!(turtle.heading(), 51.0); } + + #[test] + fn turn_towards() { + let mut turtle = Turtle::new(); + turtle.set_speed("instant"); + let mut last_delta_angle = 0.0; + let mut delta_angle = 0.0; + for n in 0..32 as u32 { + let sin = (radians::TWO_PI * n as f64 / 32.0).sin(); + let cos = (radians::TWO_PI * n as f64 / 32.0).cos(); + + turtle.turn_towards([cos, sin]); + + last_delta_angle = delta_angle; + delta_angle = sin.atan2(cos) - turtle.heading(); + // Wait until last_delta_angle is set + if n >= 1 { + // Check if the turtle is heading in the right direction + assert!(last_delta_angle >= delta_angle); + } + } + } } From f398dfce3bc2805170ae343fe000113ad46578d7 Mon Sep 17 00:00:00 2001 From: Piripant Date: Sun, 10 Dec 2017 14:57:42 +0100 Subject: [PATCH 2/4] Updated turn_towards test --- src/turtle.rs | 26 +++++++++++--------------- 1 file changed, 11 insertions(+), 15 deletions(-) diff --git a/src/turtle.rs b/src/turtle.rs index 9687ff7d..6562178f 100644 --- a/src/turtle.rs +++ b/src/turtle.rs @@ -1160,23 +1160,19 @@ mod tests { } #[test] - fn turn_towards() { + fn turn_towards() { let mut turtle = Turtle::new(); - turtle.set_speed("instant"); - let mut last_delta_angle = 0.0; - let mut delta_angle = 0.0; - for n in 0..32 as u32 { - let sin = (radians::TWO_PI * n as f64 / 32.0).sin(); - let cos = (radians::TWO_PI * n as f64 / 32.0).cos(); - - turtle.turn_towards([cos, sin]); + + // Turn from each cardinal direction to each cardinal direction + for n in 0..16 as u32 { + let original_angle = radians::TWO_PI * n as f64 / 16.0; + turtle.turn_towards([original_angle.cos(), original_angle.sin()]); + assert_eq!(turtle.heading().ceil(), original_angle.to_degrees().ceil()); - last_delta_angle = delta_angle; - delta_angle = sin.atan2(cos) - turtle.heading(); - // Wait until last_delta_angle is set - if n >= 1 { - // Check if the turtle is heading in the right direction - assert!(last_delta_angle >= delta_angle); + for i in 0..16 as u32 { + let target_angle = radians::TWO_PI * i as f64 / 16.0; + turtle.turn_towards([target_angle.cos(), target_angle.sin()]); + assert_eq!(turtle.heading().ceil(), target_angle.to_degrees().ceil()); } } } From b5698f199a8712a678d978f9664b4f75ef54bc3a Mon Sep 17 00:00:00 2001 From: Piripant Date: Sun, 10 Dec 2017 19:21:02 +0100 Subject: [PATCH 3/4] Fixed test --- src/turtle.rs | 8 ++++---- 1 file changed, 4 insertions(+), 4 deletions(-) diff --git a/src/turtle.rs b/src/turtle.rs index 6562178f..68aad525 100644 --- a/src/turtle.rs +++ b/src/turtle.rs @@ -1165,11 +1165,11 @@ mod tests { // Turn from each cardinal direction to each cardinal direction for n in 0..16 as u32 { - let original_angle = radians::TWO_PI * n as f64 / 16.0; - turtle.turn_towards([original_angle.cos(), original_angle.sin()]); - assert_eq!(turtle.heading().ceil(), original_angle.to_degrees().ceil()); - for i in 0..16 as u32 { + let original_angle = radians::TWO_PI * n as f64 / 16.0; + turtle.turn_towards([original_angle.cos(), original_angle.sin()]); + assert_eq!(turtle.heading().ceil(), original_angle.to_degrees().ceil()); + let target_angle = radians::TWO_PI * i as f64 / 16.0; turtle.turn_towards([target_angle.cos(), target_angle.sin()]); assert_eq!(turtle.heading().ceil(), target_angle.to_degrees().ceil()); From bdf72432da8dabbdb1fff4742bf5b22e74b65d07 Mon Sep 17 00:00:00 2001 From: Piripant Date: Sun, 10 Dec 2017 19:23:08 +0100 Subject: [PATCH 4/4] Cleaning code --- src/turtle.rs | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/turtle.rs b/src/turtle.rs index 68aad525..f920d315 100644 --- a/src/turtle.rs +++ b/src/turtle.rs @@ -1165,8 +1165,8 @@ mod tests { // Turn from each cardinal direction to each cardinal direction for n in 0..16 as u32 { + let original_angle = radians::TWO_PI * n as f64 / 16.0; for i in 0..16 as u32 { - let original_angle = radians::TWO_PI * n as f64 / 16.0; turtle.turn_towards([original_angle.cos(), original_angle.sin()]); assert_eq!(turtle.heading().ceil(), original_angle.to_degrees().ceil());