From e51114621be86f8ef6338dc3539e4c4d2b9d4149 Mon Sep 17 00:00:00 2001 From: David Sawatzke Date: Wed, 20 May 2020 19:46:14 +0200 Subject: [PATCH 1/4] Use powi instead of powf (it's faster) --- src/lib.rs | 28 ++++++++++++++-------------- 1 file changed, 14 insertions(+), 14 deletions(-) diff --git a/src/lib.rs b/src/lib.rs index 6e794c9..47a7548 100644 --- a/src/lib.rs +++ b/src/lib.rs @@ -100,8 +100,8 @@ pub fn rsr(end: Vector) -> Result { // get the tangent magnitude this, again, is the same as the distance // between the two circle centers since our circles have the same radius route_csc.tangent.magnitude = - ((route_csc.end.circle.center.x - route_csc.start.circle.center.x).powf(2.0) - + (route_csc.end.circle.center.y - route_csc.start.circle.center.y).powf(2.0)) + ((route_csc.end.circle.center.x - route_csc.start.circle.center.x).powi(2) + + (route_csc.end.circle.center.y - route_csc.start.circle.center.y).powi(2)) .sqrt(); // get the angle of the start circle @@ -200,10 +200,10 @@ pub fn lsl(end: Vector) -> Result { route_csc.tangent.magnitude = ((route_csc.end.circle.center.x - route_csc.start.circle.center.x) .abs() - .powf(2.0) + .powi(2) + (route_csc.end.circle.center.y - route_csc.start.circle.center.y) .abs() - .powf(2.0)) + .powi(2)) .sqrt(); // get the angle of the start circle @@ -279,8 +279,8 @@ pub fn rsl(end: Vector) -> Result { }; // check if inside tangent can even be constructed - if ((route_csc.end.circle.center.x - route_csc.start.circle.center.x).powf(2.0) - + (route_csc.end.circle.center.y - route_csc.start.circle.center.y).powf(2.0)) + if ((route_csc.end.circle.center.x - route_csc.start.circle.center.x).powi(2) + + (route_csc.end.circle.center.y - route_csc.start.circle.center.y).powi(2)) .sqrt() < 2.0 * end.magnitude { @@ -289,9 +289,9 @@ pub fn rsl(end: Vector) -> Result { // get the tangent length via some simple trigonometry route_csc.tangent.magnitude = - ((route_csc.end.circle.center.x - route_csc.start.circle.center.x).powf(2.0) - + (route_csc.end.circle.center.y - route_csc.start.circle.center.y).powf(2.0) - - (2.0 * end.magnitude).powf(2.0)) + ((route_csc.end.circle.center.x - route_csc.start.circle.center.x).powi(2) + + (route_csc.end.circle.center.y - route_csc.start.circle.center.y).powi(2) + - (2.0 * end.magnitude).powi(2)) .sqrt(); // tangent middle is the same as the middle of the straight from the center of the start @@ -387,8 +387,8 @@ pub fn lsr(end: Vector) -> Result { }; // check if inside tangent can even be constructed - if ((route_csc.end.circle.center.x - route_csc.start.circle.center.x).powf(2.0) - + (route_csc.end.circle.center.y - route_csc.start.circle.center.y).powf(2.0)) + if ((route_csc.end.circle.center.x - route_csc.start.circle.center.x).powi(2) + + (route_csc.end.circle.center.y - route_csc.start.circle.center.y).powi(2)) .sqrt() < 2.0 * end.magnitude { @@ -397,9 +397,9 @@ pub fn lsr(end: Vector) -> Result { // get the tangent length via some simple trigonometry route_csc.tangent.magnitude = - ((route_csc.end.circle.center.x - route_csc.start.circle.center.x).powf(2.0) - + (route_csc.end.circle.center.y - route_csc.start.circle.center.y).powf(2.0) - - (2.0 * end.magnitude).powf(2.0)) + ((route_csc.end.circle.center.x - route_csc.start.circle.center.x).powi(2) + + (route_csc.end.circle.center.y - route_csc.start.circle.center.y).powi(2) + - (2.0 * end.magnitude).powi(2)) .sqrt(); // tangent middle is the same as the middle of the straight from the center of the start From a80b6bc1d90738bdb13978f8603edb44728597b3 Mon Sep 17 00:00:00 2001 From: David Sawatzke Date: Wed, 20 May 2020 19:55:48 +0200 Subject: [PATCH 2/4] Use euclid `Angle` --- Cargo.toml | 1 + src/lib.rs | 226 +++++++++++++++++++---------------------------------- 2 files changed, 81 insertions(+), 146 deletions(-) diff --git a/Cargo.toml b/Cargo.toml index 8f98977..4bad0da 100644 --- a/Cargo.toml +++ b/Cargo.toml @@ -15,3 +15,4 @@ edition = "2018" [dependencies] +euclid = "0.20.11" diff --git a/src/lib.rs b/src/lib.rs index 47a7548..223fff5 100644 --- a/src/lib.rs +++ b/src/lib.rs @@ -1,11 +1,13 @@ -/*! Call all functions with a Vector as argument the vector should contain: - - the end point as origin - - the end angle as angle in degrees in clockwise direction (eg. 0° facing north, 90° facing east, ...) - - the circle radius as magnitude +//! Call all functions with a Vector as argument the vector should contain: +//! - the end point as origin +//! - the end angle as angle in degrees in clockwise direction (eg. 0° facing north, 90° facing east, ...) +//! - the circle radius as magnitude +//! +//! Start Vector is in the origin facing in positive x-direction +//! +//! Every struct defined here is 2 dimensional and uses f64 -Start Vector is in the origin facing in positive x-direction - -Every struct defined here is 2 dimensional and uses f64 */ +use euclid::Angle; /// Point pub struct Point { @@ -16,7 +18,7 @@ pub struct Point { /// Vector with origin, angle and magnitude pub struct Vector { pub origin: Point, - pub angle: f64, + pub angle: Angle, pub magnitude: f64, } @@ -29,7 +31,7 @@ pub struct Circle { /// Circle route with a circle and a angle for how long to drive on this circle pub struct CircleRoute { pub circle: Circle, - pub angle: f64, + pub angle: Angle, } /// Route with a start Circle, a tangent straight and a end Circle (eg. rsl, rsr, lsr, lsl) @@ -58,11 +60,11 @@ pub fn rsr(end: Vector) -> Result { }, radius: end.magnitude, }, - angle: 0.0, + angle: Angle::zero(), }, tangent: Vector { origin: Point { x: 0.0, y: 0.0 }, - angle: 0.0, + angle: Angle::zero(), magnitude: 0.0, }, end: CircleRoute { @@ -70,31 +72,32 @@ pub fn rsr(end: Vector) -> Result { center: Point { x: 0.0, y: 0.0 }, radius: end.magnitude, }, - angle: 0.0, + angle: Angle::zero(), }, }; // get the center point by adding the end vector to the end point // this works because the argument is the angle in positive y direction // not positive x direction so we dont have to rotate it here anymore - // the angle has to be counter clockwise though (thats why 360 - end.angle) + // the angle has to be counter clockwise though (thats why 2π - end.angle) route_csc.end.circle.center = Point { - x: end.origin.x + end.magnitude * (360.0 - end.angle).to_radians().cos(), - y: end.origin.y + end.magnitude * (360.0 - end.angle).to_radians().sin(), + x: end.origin.x + end.magnitude * (Angle::two_pi() - end.angle).get().cos(), + y: end.origin.y + end.magnitude * (Angle::two_pi() - end.angle).get().sin(), }; // get the tangent pitch which is the same as the pitch between the two // circle centers since our circles have the same radius - route_csc.tangent.angle = ((route_csc.end.circle.center.y - route_csc.start.circle.center.y) - / (route_csc.end.circle.center.x - route_csc.start.circle.center.x)) - .atan() - .to_degrees(); + route_csc.tangent.angle = Angle::radians( + ((route_csc.end.circle.center.y - route_csc.start.circle.center.y) + / (route_csc.end.circle.center.x - route_csc.start.circle.center.x)) + .atan(), + ); // if the end circle center x value is smaller than the // start circle center x value // the angle would be 180° rotated so to prevent that: if route_csc.end.circle.center.x < route_csc.start.circle.center.x { - route_csc.tangent.angle += 180.0; + route_csc.tangent.angle += Angle::pi(); } // get the tangent magnitude this, again, is the same as the distance @@ -105,37 +108,21 @@ pub fn rsr(end: Vector) -> Result { .sqrt(); // get the angle of the start circle - route_csc.start.angle = 90.0 - route_csc.tangent.angle; - - // make the angle pretty - if route_csc.start.angle < 0.0 { - route_csc.start.angle += 360.0; - } - if route_csc.start.angle >= 360.0 { - route_csc.start.angle -= 360.0; - } + route_csc.start.angle = (Angle::frac_pi_2() - route_csc.tangent.angle).positive(); // get the tangent origin by moving the vector from the start circle center // 90° to it's own direction and the magnitude of the circle radius route_csc.tangent.origin = Point { x: route_csc.start.circle.center.x - + route_csc.start.circle.radius * (180.0 - route_csc.start.angle).to_radians().cos(), + + route_csc.start.circle.radius * (Angle::pi() - route_csc.start.angle).get().cos(), y: route_csc.start.circle.center.y - + route_csc.start.circle.radius * (180.0 - route_csc.start.angle).to_radians().sin(), + + route_csc.start.circle.radius * (Angle::pi() - route_csc.start.angle).get().sin(), }; // get the angle of the start circle // the angle where we start from the tangent equals the one we finish // so we can use that in here - route_csc.end.angle = end.angle - route_csc.start.angle; - - // make the angle pretty - if route_csc.end.angle < 0.0 { - route_csc.end.angle += 360.0; - } - if route_csc.end.angle >= 360.0 { - route_csc.end.angle -= 360.0; - } + route_csc.end.angle = (end.angle - route_csc.start.angle).positive(); Ok(route_csc) } @@ -151,11 +138,11 @@ pub fn lsl(end: Vector) -> Result { }, radius: end.magnitude, }, - angle: 0.0, + angle: Angle::zero(), }, tangent: Vector { origin: Point { x: 0.0, y: 0.0 }, - angle: 0.0, + angle: Angle::zero(), magnitude: 0.0, }, end: CircleRoute { @@ -163,36 +150,33 @@ pub fn lsl(end: Vector) -> Result { center: Point { x: 0.0, y: 0.0 }, radius: end.magnitude, }, - angle: 0.0, + angle: Angle::zero(), }, }; // get the center point by adding the end vector to the end point - // we have to rotate the vector 180° (90° because the given angle is from the y axis - // and 90 more to not get the tangent but the vector to the center point) + // we have to rotate the vector π (π/2 because the given angle is from the y axis + // and π/2 more to not get the tangent but the vector to the center point) // and again we have to use the counter clockwise direction route_csc.end.circle.center = Point { - x: end.origin.x + end.magnitude * (180.0 - end.angle).to_radians().cos(), - y: end.origin.y + end.magnitude * (180.0 - end.angle).to_radians().sin(), + x: end.origin.x + end.magnitude * (Angle::pi() - end.angle).get().cos(), + y: end.origin.y + end.magnitude * (Angle::pi() - end.angle).get().sin(), }; // get the tangent pitch which is the same as the pitch between the two // circle centers since our circles have the same radius - route_csc.tangent.angle = ((route_csc.end.circle.center.y - route_csc.start.circle.center.y) - / (route_csc.end.circle.center.x - route_csc.start.circle.center.x)) - .atan() - .to_degrees(); + route_csc.tangent.angle = Angle::radians( + ((route_csc.end.circle.center.y - route_csc.start.circle.center.y) + / (route_csc.end.circle.center.x - route_csc.start.circle.center.x)) + .atan(), + ) + .positive(); // if the end circle center x value is smaller than the // start circle center x value - // the angle would be 180° rotated so to prevent that: + // the angle would be π rotated so to prevent that: if route_csc.end.circle.center.x < route_csc.start.circle.center.x { - route_csc.tangent.angle += 180.0; - } - - // make the angle positive - if route_csc.tangent.angle < 0.0 { - route_csc.tangent.angle += 360.0; + route_csc.tangent.angle = (route_csc.tangent.angle + Angle::pi()).positive(); } // get the tangent magnitude this, again, is the same as the distance @@ -207,37 +191,21 @@ pub fn lsl(end: Vector) -> Result { .sqrt(); // get the angle of the start circle - route_csc.start.angle = route_csc.tangent.angle - 90.0; - - // make the angle pretty - if route_csc.start.angle < 0.0 { - route_csc.start.angle += 360.0; - } - if route_csc.start.angle >= 360.0 { - route_csc.start.angle -= 360.0; - } + route_csc.start.angle = (route_csc.tangent.angle - Angle::frac_pi_2()).positive(); // get the tangent origin by moving the vector from the start circle center // 90° to it's own direction and the magnitude of the circle radius route_csc.tangent.origin = Point { x: route_csc.start.circle.center.x - + route_csc.start.circle.radius * route_csc.start.angle.to_radians().cos(), + + route_csc.start.circle.radius * route_csc.start.angle.get().cos(), y: route_csc.start.circle.center.y - + route_csc.start.circle.radius * route_csc.start.angle.to_radians().sin(), + + route_csc.start.circle.radius * route_csc.start.angle.get().sin(), }; // get the angle of the start circle // the angle where we start from the tangent equals the one we finish // so we can use that in here - route_csc.end.angle = end.angle - route_csc.start.angle; - - // make the angle pretty - if route_csc.end.angle < 0.0 { - route_csc.end.angle += 360.0; - } - if route_csc.end.angle >= 360.0 { - route_csc.end.angle -= 360.0; - } + route_csc.end.angle = (end.angle - route_csc.start.angle).positive(); Ok(route_csc) } @@ -253,11 +221,11 @@ pub fn rsl(end: Vector) -> Result { }, radius: end.magnitude, }, - angle: 0.0, + angle: Angle::zero(), }, tangent: Vector { origin: Point { x: 0.0, y: 0.0 }, - angle: 0.0, + angle: Angle::zero(), magnitude: 0.0, }, end: CircleRoute { @@ -265,17 +233,17 @@ pub fn rsl(end: Vector) -> Result { center: Point { x: 0.0, y: 0.0 }, radius: end.magnitude, }, - angle: 0.0, + angle: Angle::zero(), }, }; // get the center point by adding the end vector to the end point - // we have to rotate the vector 180° (90° because the given angle is from the y axis - // and 90 more to not get the tangent but the vector to the center point) + // we have to rotate the vector π (π/2 because the given angle is from the y axis + // and π/2 more to not get the tangent but the vector to the center point) // and again we have to use the counter clockwise direction route_csc.end.circle.center = Point { - x: end.origin.x + end.magnitude * (180.0 - end.angle).to_radians().cos(), - y: end.origin.y + end.magnitude * (180.0 - end.angle).to_radians().sin(), + x: end.origin.x + end.magnitude * (Angle::pi() - end.angle).get().cos(), + y: end.origin.y + end.magnitude * (Angle::pi() - end.angle).get().sin(), }; // check if inside tangent can even be constructed @@ -301,51 +269,34 @@ pub fn rsl(end: Vector) -> Result { }; // get the tangent angle - route_csc.tangent.angle = ((route_csc.end.circle.center.y - tangent_middle.y) - / (route_csc.end.circle.center.x - tangent_middle.x)) - .atan() - .to_degrees() - - (2.0 * end.magnitude / route_csc.tangent.magnitude) + route_csc.tangent.angle = Angle::radians( + ((route_csc.end.circle.center.y - tangent_middle.y) + / (route_csc.end.circle.center.x - tangent_middle.x)) .atan() - .to_degrees(); + - (2.0 * end.magnitude / route_csc.tangent.magnitude).atan(), + ); // if the end circle center x value is smaller than the // start circle center x value - // the angle would be 180° rotated so to prevent that: + // the angle would be π rotated so to prevent that: if route_csc.end.circle.center.x < route_csc.start.circle.center.x { - route_csc.tangent.angle += 180.0; + route_csc.tangent.angle += Angle::pi(); } // get the angle of the start circle - route_csc.start.angle = 90.0 - route_csc.tangent.angle; - - // make the angle pretty - if route_csc.start.angle < 0.0 { - route_csc.start.angle += 360.0; - } - if route_csc.start.angle >= 360.0 { - route_csc.start.angle -= 360.0; - } + route_csc.start.angle = (Angle::frac_pi_2() - route_csc.tangent.angle).positive(); // get the tangent origin by moving the vector from the start circle center // along its right angle vector route_csc.tangent.origin = Point { x: route_csc.start.circle.center.x - + route_csc.start.circle.radius * (180.0 - route_csc.start.angle).to_radians().cos(), + + route_csc.start.circle.radius * (Angle::pi() - route_csc.start.angle).get().cos(), y: route_csc.start.circle.center.y - + route_csc.start.circle.radius * (180.0 - route_csc.start.angle).to_radians().sin(), + + route_csc.start.circle.radius * (Angle::pi() - route_csc.start.angle).get().sin(), }; // get the angle of the end circle - route_csc.end.angle = (90.0 - end.angle) - route_csc.tangent.angle; - - // make the angle pretty - if route_csc.end.angle < 0.0 { - route_csc.end.angle += 360.0; - } - if route_csc.end.angle >= 360.0 { - route_csc.end.angle -= 360.0; - } + route_csc.end.angle = ((Angle::frac_pi_2() - end.angle) - route_csc.tangent.angle).positive(); Ok(route_csc) } @@ -361,11 +312,11 @@ pub fn lsr(end: Vector) -> Result { }, radius: end.magnitude, }, - angle: 0.0, + angle: Angle::zero(), }, tangent: Vector { origin: Point { x: 0.0, y: 0.0 }, - angle: 0.0, + angle: Angle::zero(), magnitude: 0.0, }, end: CircleRoute { @@ -373,17 +324,17 @@ pub fn lsr(end: Vector) -> Result { center: Point { x: 0.0, y: 0.0 }, radius: end.magnitude, }, - angle: 0.0, + angle: Angle::zero(), }, }; // get the center point by adding the end vector to the end point // this works because the argument is the angle in positive y direction // not positive x direction so we dont have to rotate it here anymore - // the angle has to be counter clockwise though (thats why 360 - end.angle) + // the angle has to be counter clockwise though (thats why 2π - end.angle) route_csc.end.circle.center = Point { - x: end.origin.x + end.magnitude * (360.0 - end.angle).to_radians().cos(), - y: end.origin.y + end.magnitude * (360.0 - end.angle).to_radians().sin(), + x: end.origin.x + end.magnitude * (Angle::two_pi() - end.angle).get().cos(), + y: end.origin.y + end.magnitude * (Angle::two_pi() - end.angle).get().sin(), }; // check if inside tangent can even be constructed @@ -409,51 +360,34 @@ pub fn lsr(end: Vector) -> Result { }; // get the tangent angle - route_csc.tangent.angle = ((route_csc.end.circle.center.y - tangent_middle.y) - / (route_csc.end.circle.center.x - tangent_middle.x)) - .atan() - .to_degrees() - + (2.0 * end.magnitude / route_csc.tangent.magnitude) + route_csc.tangent.angle = Angle::radians( + ((route_csc.end.circle.center.y - tangent_middle.y) + / (route_csc.end.circle.center.x - tangent_middle.x)) .atan() - .to_degrees(); + + (2.0 * end.magnitude / route_csc.tangent.magnitude).atan(), + ); // if the end circle center x value is smaller than the // start circle center x value // the angle would be 180° rotated so to prevent that: if route_csc.end.circle.center.x < route_csc.start.circle.center.x { - route_csc.tangent.angle += 180.0; + route_csc.tangent.angle += Angle::pi(); } // get the angle of the start circle - route_csc.start.angle = route_csc.tangent.angle - 90.0; - - // make the angle pretty - if route_csc.start.angle < 0.0 { - route_csc.start.angle += 360.0; - } - if route_csc.start.angle >= 360.0 { - route_csc.start.angle -= 360.0; - } + route_csc.start.angle = (route_csc.tangent.angle - Angle::frac_pi_2()).positive(); // get the tangent origin by moving the vector from the start circle center // 90° to it's own direction and the magnitude of the circle radius route_csc.tangent.origin = Point { x: route_csc.start.circle.center.x - + route_csc.start.circle.radius * route_csc.start.angle.to_radians().cos(), + + route_csc.start.circle.radius * route_csc.start.angle.get().cos(), y: route_csc.start.circle.center.y - + route_csc.start.circle.radius * route_csc.start.angle.to_radians().sin(), + + route_csc.start.circle.radius * route_csc.start.angle.get().sin(), }; // get the angle of the end circle - route_csc.end.angle = (90.0 - end.angle) - route_csc.tangent.angle; - - // make the angle pretty - if route_csc.end.angle < 0.0 { - route_csc.end.angle += 360.0; - } - if route_csc.end.angle >= 360.0 { - route_csc.end.angle -= 360.0; - } + route_csc.end.angle = ((Angle::frac_pi_2() - end.angle) - route_csc.tangent.angle).positive(); Ok(route_csc) } From 788ace12c843fe204941c063f33c140afe1a8706 Mon Sep 17 00:00:00 2001 From: David Sawatzke Date: Wed, 20 May 2020 21:15:56 +0200 Subject: [PATCH 3/4] Use euclide `Point2D` --- src/lib.rs | 132 +++++++++++++++++++++-------------------------------- 1 file changed, 53 insertions(+), 79 deletions(-) diff --git a/src/lib.rs b/src/lib.rs index 223fff5..812247e 100644 --- a/src/lib.rs +++ b/src/lib.rs @@ -7,13 +7,11 @@ //! //! Every struct defined here is 2 dimensional and uses f64 -use euclid::Angle; +use euclid::{Angle, Point2D, Rotation2D, UnknownUnit}; -/// Point -pub struct Point { - pub x: f64, - pub y: f64, -} +type Point = Point2D; +type Vector2D = euclid::Vector2D; +type Rotation = Rotation2D; /// Vector with origin, angle and magnitude pub struct Vector { @@ -54,22 +52,19 @@ pub fn rsr(end: Vector) -> Result { let mut route_csc = RouteCSC { start: CircleRoute { circle: Circle { - center: Point { - x: end.magnitude, - y: 0.0, - }, + center: Point::new(end.magnitude, 0.0), radius: end.magnitude, }, angle: Angle::zero(), }, tangent: Vector { - origin: Point { x: 0.0, y: 0.0 }, + origin: Point::zero(), angle: Angle::zero(), magnitude: 0.0, }, end: CircleRoute { circle: Circle { - center: Point { x: 0.0, y: 0.0 }, + center: Point::zero(), radius: end.magnitude, }, angle: Angle::zero(), @@ -79,11 +74,11 @@ pub fn rsr(end: Vector) -> Result { // get the center point by adding the end vector to the end point // this works because the argument is the angle in positive y direction // not positive x direction so we dont have to rotate it here anymore - // the angle has to be counter clockwise though (thats why 2π - end.angle) - route_csc.end.circle.center = Point { - x: end.origin.x + end.magnitude * (Angle::two_pi() - end.angle).get().cos(), - y: end.origin.y + end.magnitude * (Angle::two_pi() - end.angle).get().sin(), - }; + // the angle has to be counter clockwise though (thats why we use the inverse end.angle) + route_csc.end.circle.center = end.origin + + Rotation::new(end.angle) + .inverse() + .transform_vector(Vector2D::new(end.magnitude, 0.0)); // get the tangent pitch which is the same as the pitch between the two // circle centers since our circles have the same radius @@ -112,12 +107,9 @@ pub fn rsr(end: Vector) -> Result { // get the tangent origin by moving the vector from the start circle center // 90° to it's own direction and the magnitude of the circle radius - route_csc.tangent.origin = Point { - x: route_csc.start.circle.center.x - + route_csc.start.circle.radius * (Angle::pi() - route_csc.start.angle).get().cos(), - y: route_csc.start.circle.center.y - + route_csc.start.circle.radius * (Angle::pi() - route_csc.start.angle).get().sin(), - }; + route_csc.tangent.origin = route_csc.start.circle.center + + Rotation::new(Angle::pi() - end.angle) + .transform_vector(Vector2D::new(route_csc.start.circle.radius, 0.0)); // get the angle of the start circle // the angle where we start from the tangent equals the one we finish @@ -132,22 +124,19 @@ pub fn lsl(end: Vector) -> Result { let mut route_csc = RouteCSC { start: CircleRoute { circle: Circle { - center: Point { - x: -end.magnitude, - y: 0.0, - }, + center: Point::new(-end.magnitude, 0.0), radius: end.magnitude, }, angle: Angle::zero(), }, tangent: Vector { - origin: Point { x: 0.0, y: 0.0 }, + origin: Point::zero(), angle: Angle::zero(), magnitude: 0.0, }, end: CircleRoute { circle: Circle { - center: Point { x: 0.0, y: 0.0 }, + center: Point::zero(), radius: end.magnitude, }, angle: Angle::zero(), @@ -158,10 +147,9 @@ pub fn lsl(end: Vector) -> Result { // we have to rotate the vector π (π/2 because the given angle is from the y axis // and π/2 more to not get the tangent but the vector to the center point) // and again we have to use the counter clockwise direction - route_csc.end.circle.center = Point { - x: end.origin.x + end.magnitude * (Angle::pi() - end.angle).get().cos(), - y: end.origin.y + end.magnitude * (Angle::pi() - end.angle).get().sin(), - }; + route_csc.end.circle.center = end.origin + + Rotation::new(Angle::pi() - end.angle) + .transform_vector(Vector2D::new(end.magnitude, 0.0)); // get the tangent pitch which is the same as the pitch between the two // circle centers since our circles have the same radius @@ -195,12 +183,9 @@ pub fn lsl(end: Vector) -> Result { // get the tangent origin by moving the vector from the start circle center // 90° to it's own direction and the magnitude of the circle radius - route_csc.tangent.origin = Point { - x: route_csc.start.circle.center.x - + route_csc.start.circle.radius * route_csc.start.angle.get().cos(), - y: route_csc.start.circle.center.y - + route_csc.start.circle.radius * route_csc.start.angle.get().sin(), - }; + route_csc.tangent.origin = route_csc.start.circle.center + + Rotation::new(route_csc.start.angle) + .transform_vector(Vector2D::new(route_csc.start.circle.radius, 0.0)); // get the angle of the start circle // the angle where we start from the tangent equals the one we finish @@ -215,22 +200,19 @@ pub fn rsl(end: Vector) -> Result { let mut route_csc = RouteCSC { start: CircleRoute { circle: Circle { - center: Point { - x: end.magnitude, - y: 0.0, - }, + center: Point::new(end.magnitude, 0.0), radius: end.magnitude, }, angle: Angle::zero(), }, tangent: Vector { - origin: Point { x: 0.0, y: 0.0 }, + origin: Point::zero(), angle: Angle::zero(), magnitude: 0.0, }, end: CircleRoute { circle: Circle { - center: Point { x: 0.0, y: 0.0 }, + center: Point::zero(), radius: end.magnitude, }, angle: Angle::zero(), @@ -241,10 +223,9 @@ pub fn rsl(end: Vector) -> Result { // we have to rotate the vector π (π/2 because the given angle is from the y axis // and π/2 more to not get the tangent but the vector to the center point) // and again we have to use the counter clockwise direction - route_csc.end.circle.center = Point { - x: end.origin.x + end.magnitude * (Angle::pi() - end.angle).get().cos(), - y: end.origin.y + end.magnitude * (Angle::pi() - end.angle).get().sin(), - }; + route_csc.end.circle.center = end.origin + + Rotation::new(Angle::pi() - end.angle) + .transform_vector(Vector2D::new(end.magnitude, 0.0)); // check if inside tangent can even be constructed if ((route_csc.end.circle.center.x - route_csc.start.circle.center.x).powi(2) @@ -263,10 +244,11 @@ pub fn rsl(end: Vector) -> Result { .sqrt(); // tangent middle is the same as the middle of the straight from the center of the start - let tangent_middle = Point { - x: (route_csc.end.circle.center.x + route_csc.start.circle.center.x) / 2.0, - y: (route_csc.end.circle.center.y + route_csc.start.circle.center.y) / 2.0, - }; + let tangent_middle = route_csc + .end + .circle + .center + .lerp(route_csc.start.circle.center, 0.5); // get the tangent angle route_csc.tangent.angle = Angle::radians( @@ -288,12 +270,9 @@ pub fn rsl(end: Vector) -> Result { // get the tangent origin by moving the vector from the start circle center // along its right angle vector - route_csc.tangent.origin = Point { - x: route_csc.start.circle.center.x - + route_csc.start.circle.radius * (Angle::pi() - route_csc.start.angle).get().cos(), - y: route_csc.start.circle.center.y - + route_csc.start.circle.radius * (Angle::pi() - route_csc.start.angle).get().sin(), - }; + route_csc.tangent.origin = route_csc.start.circle.center + + Rotation::new(Angle::pi() - route_csc.start.angle) + .transform_vector(Vector2D::new(route_csc.start.circle.radius, 0.0)); // get the angle of the end circle route_csc.end.angle = ((Angle::frac_pi_2() - end.angle) - route_csc.tangent.angle).positive(); @@ -306,22 +285,19 @@ pub fn lsr(end: Vector) -> Result { let mut route_csc = RouteCSC { start: CircleRoute { circle: Circle { - center: Point { - x: -end.magnitude, - y: 0.0, - }, + center: Point::new(-end.magnitude, 0.0), radius: end.magnitude, }, angle: Angle::zero(), }, tangent: Vector { - origin: Point { x: 0.0, y: 0.0 }, + origin: Point::zero(), angle: Angle::zero(), magnitude: 0.0, }, end: CircleRoute { circle: Circle { - center: Point { x: 0.0, y: 0.0 }, + center: Point::zero(), radius: end.magnitude, }, angle: Angle::zero(), @@ -332,10 +308,10 @@ pub fn lsr(end: Vector) -> Result { // this works because the argument is the angle in positive y direction // not positive x direction so we dont have to rotate it here anymore // the angle has to be counter clockwise though (thats why 2π - end.angle) - route_csc.end.circle.center = Point { - x: end.origin.x + end.magnitude * (Angle::two_pi() - end.angle).get().cos(), - y: end.origin.y + end.magnitude * (Angle::two_pi() - end.angle).get().sin(), - }; + route_csc.end.circle.center = end.origin + + Rotation::new(end.angle) + .inverse() + .transform_vector(Vector2D::new(end.magnitude, 0.0)); // check if inside tangent can even be constructed if ((route_csc.end.circle.center.x - route_csc.start.circle.center.x).powi(2) @@ -354,10 +330,11 @@ pub fn lsr(end: Vector) -> Result { .sqrt(); // tangent middle is the same as the middle of the straight from the center of the start - let tangent_middle = Point { - x: (route_csc.end.circle.center.x + route_csc.start.circle.center.x) / 2.0, - y: (route_csc.end.circle.center.y + route_csc.start.circle.center.y) / 2.0, - }; + let tangent_middle = route_csc + .end + .circle + .center + .lerp(route_csc.start.circle.center, 0.5); // get the tangent angle route_csc.tangent.angle = Angle::radians( @@ -379,12 +356,9 @@ pub fn lsr(end: Vector) -> Result { // get the tangent origin by moving the vector from the start circle center // 90° to it's own direction and the magnitude of the circle radius - route_csc.tangent.origin = Point { - x: route_csc.start.circle.center.x - + route_csc.start.circle.radius * route_csc.start.angle.get().cos(), - y: route_csc.start.circle.center.y - + route_csc.start.circle.radius * route_csc.start.angle.get().sin(), - }; + route_csc.tangent.origin = route_csc.start.circle.center + + Rotation::new(route_csc.start.angle) + .transform_vector(Vector2D::new(route_csc.start.circle.radius, 0.0)); // get the angle of the end circle route_csc.end.angle = ((Angle::frac_pi_2() - end.angle) - route_csc.tangent.angle).positive(); From ddea6ecf73ea2544a777fe988dfbb07e739bc28f Mon Sep 17 00:00:00 2001 From: David Sawatzke Date: Wed, 20 May 2020 21:38:22 +0200 Subject: [PATCH 4/4] Make Angle & Point public types --- src/lib.rs | 9 +++++---- 1 file changed, 5 insertions(+), 4 deletions(-) diff --git a/src/lib.rs b/src/lib.rs index 812247e..a8d4344 100644 --- a/src/lib.rs +++ b/src/lib.rs @@ -7,16 +7,17 @@ //! //! Every struct defined here is 2 dimensional and uses f64 -use euclid::{Angle, Point2D, Rotation2D, UnknownUnit}; +use euclid::{Point2D, Rotation2D, UnknownUnit}; -type Point = Point2D; +pub type Angle = euclid::Angle; +pub type Point = Point2D; type Vector2D = euclid::Vector2D; type Rotation = Rotation2D; /// Vector with origin, angle and magnitude pub struct Vector { pub origin: Point, - pub angle: Angle, + pub angle: Angle, pub magnitude: f64, } @@ -29,7 +30,7 @@ pub struct Circle { /// Circle route with a circle and a angle for how long to drive on this circle pub struct CircleRoute { pub circle: Circle, - pub angle: Angle, + pub angle: Angle, } /// Route with a start Circle, a tangent straight and a end Circle (eg. rsl, rsr, lsr, lsl)