@ -25,43 +25,33 @@ pub enum Error {
/// Vector with origin, angle and magnitude
#[ derive(Debug, Copy, Clone) ]
pub struct Vector {
pub struct StraightPath {
pub origin : Point ,
pub angle : Angle ,
pub magnitude : f64 ,
pub vector : Vector ,
}
impl Vector {
impl StraightPath {
/// approximate equality to other Vector
pub fn approx_eq ( & self , other : Self ) -> bool {
if ! ApproxEq ::approx_eq ( & self . origin , & other . origin ) {
false
} else if ! ApproxEq ::approx_eq ( & self . magnitude , & other . magnitude ) {
false
} else if ! ( ApproxEq ::approx_eq ( & self . angle , & other . angle )
| | ApproxEq ::approx_eq ( & self . angle . signed ( ) , & other . angle . signed ( ) ) )
{
false
} else {
true
}
ApproxEq ::approx_eq ( & self . vector , & other . vector )
& & ApproxEq ::approx_eq ( & self . origin , & other . origin )
}
}
/// Circle vector (Circle + Angle)
#[ derive(Debug, Copy, Clone) ]
pub struct Circle Vector {
pub struct CirclePath {
pub center : Point ,
pub radius : f64 ,
pub angle : Angle ,
}
impl Circle Vector {
impl Circle Path {
///get the length of the circle vector
pub fn get_length ( & self ) -> f64 {
self . angle . radians * self . radius
}
/// approximate equality to other Circle Vector
/// approximate equality to other Circle Path
pub fn approx_eq ( & self , other : Self ) -> bool {
if ! ApproxEq ::approx_eq ( & self . center , & other . center ) {
false
@ -80,17 +70,17 @@ impl CircleVector {
/// Route with a start Circle, a tangent straight and a end Circle
#[ derive(Debug, Copy, Clone) ]
pub struct RouteCSC {
pub start : Circle Vector ,
pub tangent : Vector ,
pub end : Circle Vector ,
pub start : Circle Path ,
pub tangent : StraightPath ,
pub end : Circle Path ,
}
/// Route with 3 Circles
#[ derive(Debug, Copy, Clone) ]
pub struct RouteCCC {
pub start : Circle Vector ,
pub middle : Circle Vector ,
pub end : Circle Vector ,
pub start : Circle Path ,
pub middle : Circle Path ,
pub end : Circle Path ,
}
#[ derive(Debug, Copy, Clone) ]
@ -102,311 +92,285 @@ pub enum Path {
/// Route with a start Circle, a tangent straight and a end Circle
impl RouteCSC {
/// right straight right route
pub fn rsr ( end : Vector ) -> Result < Self , Error > {
let mut route_csc = RouteCSC {
start : CircleVector {
center : Point ::new ( end . magnitude , 0.0 ) ,
radius : end . magnitude ,
angle : Angle ::zero ( ) ,
} ,
tangent : Vector {
origin : Point ::zero ( ) ,
angle : Angle ::zero ( ) ,
magnitude : 0.0 ,
} ,
end : CircleVector {
center : Point ::zero ( ) ,
radius : end . magnitude ,
angle : Angle ::zero ( ) ,
} ,
} ;
pub fn rsr ( radius : f64 , end_point : Point , end_angle : Angle ) -> Result < Self , Error > {
let start_center = Point ::new ( radius , 0.0 ) ;
// 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 we use the inverse end.angle)
route_csc . end . center = end . origin
+ Rotation ::new ( end . angle)
let end_center = end_point
+ Rotation ::new ( end_angle )
. inverse ( )
. transform_vector ( Vector 2D::new ( end . magnitude , 0.0 ) ) ;
. transform_vector ( Vector ::new ( radius , 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
route_csc . tangent . angle = Angle ::radians (
( ( route_csc . end . center . y - route_csc . start . center . y )
/ ( route_csc . end . center . x - route_csc . start . center . x ) )
. atan ( ) ,
let mut tangent_angle = Angle ::radians (
( ( end_center . y - start_center . y ) / ( end_center . x - start_center . x ) ) . atan ( ) ,
) ;
// if the end circle center x value is smaller than the
// start circle center x value
// the angle would be rotated by π so to prevent that:
if route_csc. end . center . x < route_csc . start . center. x {
route_csc. tangent . angle + = Angle ::pi ( ) ;
if end_center. x < start_ center. x {
tangent_ angle + = Angle ::pi ( ) ;
}
// 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 . center . x - route_csc . start . center. x ) . powi ( 2 )
+ ( route_csc. end . center . y - route_csc . start . center. y ) . powi ( 2 ) )
let tangent_magnitude = ( ( end_center . x - start_ center. x ) . powi ( 2 )
+ ( end_center. y - start_ center. y ) . powi ( 2 ) )
. sqrt ( ) ;
// get the angle of the start circle
route_csc . start . angle = ( Angle ::frac_pi_2 ( ) - route_csc. tangent . angle) . positive ( ) ;
let start_ angle = ( Angle ::frac_pi_2 ( ) - tangent_ angle) . positive ( ) ;
// get the tangent origin by moving the vector from the start circle center
// π/2 to it's own direction and the magnitude of the circle radius
route_csc . tangent . origin = route_csc . start . center
+ Rotation ::new ( Angle ::pi ( ) - end . angle )
. transform_vector ( Vector2D ::new ( route_csc . start . radius , 0.0 ) ) ;
let tangent_origin = start_center
+ Rotation ::new ( Angle ::pi ( ) - end_angle ) . transform_vector ( Vector ::new ( radius , 0.0 ) ) ;
// 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 ) . positive ( ) ;
Ok ( route_csc )
}
let end_angle = ( end_angle - start_angle ) . positive ( ) ;
/// left straight left route
pub fn lsl ( end : Vector ) -> Result < Self , Error > {
let mut route_csc = RouteCSC {
start : CircleVector {
center : Point ::new ( - end . magnitude , 0.0 ) ,
radius : end . magnitude ,
angle : Angle ::zero ( ) ,
Ok ( Self {
start : CirclePath {
center : start_center ,
radius : radius ,
angle : start_angle ,
} ,
tangent : Vector {
origin : Point ::zero ( ) ,
angle : Angle ::zero ( ) ,
magnitude : 0.0 ,
tangent : StraightPath {
origin : tangent_origin ,
vector : Vector ::from_angle_and_length ( tangent_angle , tangent_magnitude ) ,
} ,
end : Circle Vector {
center : Point::zero ( ) ,
radius : end. magnitude ,
angle : Angle::zero ( ) ,
end : Circle Path {
center : end_center ,
radius : radius ,
angle : end_angle ,
} ,
} ;
} )
}
/// left straight left route
pub fn lsl ( radius : f64 , end_point : Point , end_angle : Angle ) -> Result < Self , Error > {
let start_center = Point ::new ( - radius , 0.0 ) ;
// get the center point by adding the end vector to the end 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 . center = end . origin
+ Rotation ::new ( Angle ::pi ( ) - end . angle )
. transform_vector ( Vector2D ::new ( end . magnitude , 0.0 ) ) ;
let end_center = end_point
+ Rotation ::new ( Angle ::pi ( ) - end_angle ) . transform_vector ( Vector ::new ( radius , 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
route_csc . tangent . angle = Angle ::radians (
( ( route_csc . end . center . y - route_csc . start . center . y )
/ ( route_csc . end . center . x - route_csc . start . center . x ) )
. atan ( ) ,
let mut tangent_angle = Angle ::radians (
( ( end_center . y - start_center . y ) / ( end_center . x - start_center . x ) ) . atan ( ) ,
)
. positive ( ) ;
// if the end circle center x value is smaller than the
// start circle center x value
// the angle would be π rotated so to prevent that:
if route_csc. end . center . x < route_csc . start . center. x {
route_csc. tangent . angle = ( route_csc . tangent . angle + Angle ::pi ( ) ) . positive ( ) ;
if end_center. x < start_ center. x {
tangent_angle = ( tangent_ angle + Angle ::pi ( ) ) . positive ( ) ;
}
// 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 . center . x - route_csc . start . center . x )
. abs ( )
. powi ( 2 )
+ ( route_csc . end . center . y - route_csc . start . center . y )
. abs ( )
. powi ( 2 ) )
let tangent_magnitude = ( ( end_center . x - start_center . x ) . abs ( ) . powi ( 2 )
+ ( end_center . y - start_center . y ) . abs ( ) . powi ( 2 ) )
. sqrt ( ) ;
// get the angle of the start circle
route_csc . start . angle = ( route_csc . tangent . angle - Angle ::frac_pi_2 ( ) ) . positive ( ) ;
let start_angle = ( tangent_angle - Angle ::frac_pi_2 ( ) ) . positive ( ) ;
// get the tangent origin by moving the vector from the start circle center
// π/2 to it's own direction and the magnitude of the circle radius
route_csc . tangent . origin = route_csc . start . center
+ Rotation ::new ( route_csc . start . angle )
. transform_vector ( Vector2D ::new ( route_csc . start . radius , 0.0 ) ) ;
let tangent_origin =
start_center + Rotation ::new ( start_angle ) . transform_vector ( Vector ::new ( radius , 0.0 ) ) ;
// 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 ) . positive ( ) ;
Ok ( route_csc )
}
let end_angle = ( end_angle - start_angle ) . positive ( ) ;
/// right straight left route
pub fn rsl ( end : Vector ) -> Result < Self , Error > {
let mut route_csc = RouteCSC {
start : CircleVector {
center : Point ::new ( end . magnitude , 0.0 ) ,
radius : end . magnitude ,
angle : Angle ::zero ( ) ,
Ok ( Self {
start : CirclePath {
center : start_center ,
radius : radius ,
angle : start_angle ,
} ,
tangent : Vector {
origin : Point ::zero ( ) ,
angle : Angle ::zero ( ) ,
magnitude : 0.0 ,
tangent : StraightPath {
origin : tangent_origin ,
vector : Vector ::from_angle_and_length ( tangent_angle , tangent_magnitude ) ,
} ,
end : Circle Vector {
center : Point::zero ( ) ,
radius : end. magnitude ,
angle : Angle::zero ( ) ,
end : Circle Path {
center : end_center ,
radius : radius ,
angle : end_angle ,
} ,
} ;
} )
}
/// right straight left route
pub fn rsl ( radius : f64 , end_point : Point , end_angle : Angle ) -> Result < Self , Error > {
let start_center = Point ::new ( radius , 0.0 ) ;
// get the center point by adding the end vector to the end 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 . center = end . origin
+ Rotation ::new ( Angle ::pi ( ) - end . angle )
. transform_vector ( Vector2D ::new ( end . magnitude , 0.0 ) ) ;
let end_center = end_point
+ Rotation ::new ( Angle ::pi ( ) - end_angle ) . transform_vector ( Vector ::new ( radius , 0.0 ) ) ;
// check if inside tangent can even be constructed
if ( ( route_csc . end . center . x - route_csc . start . center . x ) . powi ( 2 )
+ ( route_csc . end . center . y - route_csc . start . center . y ) . powi ( 2 ) )
. sqrt ( )
< 2.0 * end . magnitude
if ( ( end_center . x - start_center . x ) . powi ( 2 ) + ( end_center . y - start_center . y ) . powi ( 2 ) )
. sqrt ( )
< 2.0 * radius
{
return Err ( Error ::CirclesTooClose ) ;
}
// get the tangent length via some simple trigonometry
route_csc . tangent . magnitude = ( ( route_csc . end . center . x - route_csc . start . center. x ) . powi ( 2 )
+ ( route_csc. end . center . y - route_csc . start . center. y ) . powi ( 2 )
- ( 2.0 * end. magnitude ) . powi ( 2 ) )
let tangent_magnitude = ( ( end_center . x - start_ center. x ) . powi ( 2 )
+ ( end_center. y - start_ center. y ) . powi ( 2 )
- ( 2.0 * radius ) . powi ( 2 ) )
. sqrt ( ) ;
// tangent middle is the same as the middle of the straight from the center of the start
let tangent_middle = route_csc. end . center . lerp ( route_csc . start . center, 0.5 ) ;
let tangent_middle = end_center. lerp ( start_ center, 0.5 ) ;
// get the tangent angle
route_csc . tangent . angle = Angle ::radians (
( ( route_csc . end . center . y - tangent_middle . y )
/ ( route_csc . end . center . x - tangent_middle . x ) )
. atan ( )
- ( 2.0 * end . magnitude / route_csc . tangent . magnitude ) . atan ( ) ,
let mut tangent_angle = Angle ::radians (
( ( end_center . y - tangent_middle . y ) / ( end_center . x - tangent_middle . x ) ) . atan ( )
- ( 2.0 * radius / tangent_magnitude ) . atan ( ) ,
) ;
// if the end circle center x value is smaller than the
// start circle center x value
// the angle would be π rotated so to prevent that:
if route_csc. end . center . x < route_csc . start . center. x {
route_csc. tangent . angle + = Angle ::pi ( ) ;
if end_center. x < start_ center. x {
tangent_ angle + = Angle ::pi ( ) ;
}
// get the angle of the start circle
route_csc . start . angle = ( Angle ::frac_pi_2 ( ) - route_csc. tangent . angle) . positive ( ) ;
let start_ angle = ( Angle ::frac_pi_2 ( ) - 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 = route_csc . start . center
+ Rotation ::new ( Angle ::pi ( ) - route_csc . start . angle )
. transform_vector ( Vector2D ::new ( route_csc . start . radius , 0.0 ) ) ;
let tangent_origin = start_center
+ Rotation ::new ( Angle ::pi ( ) - start_angle ) . transform_vector ( Vector ::new ( 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 ( ) ;
let end_angle = ( ( Angle ::frac_pi_2 ( ) - end_angle ) - tangent_angle ) . positive ( ) ;
Ok ( route_csc )
}
/// left straight right route
pub fn lsr ( end : Vector ) -> Result < Self , Error > {
let mut route_csc = RouteCSC {
start : CircleVector {
center : Point ::new ( - end . magnitude , 0.0 ) ,
radius : end . magnitude ,
angle : Angle ::zero ( ) ,
Ok ( Self {
start : CirclePath {
center : start_center ,
radius : radius ,
angle : start_angle ,
} ,
tangent : Vector {
origin : Point ::zero ( ) ,
angle : Angle ::zero ( ) ,
magnitude : 0.0 ,
tangent : StraightPath {
origin : tangent_origin ,
vector : Vector ::from_angle_and_length ( tangent_angle , tangent_magnitude ) ,
} ,
end : Circle Vector {
center : Point::zero ( ) ,
radius : end. magnitude ,
angle : Angle::zero ( ) ,
end : Circle Path {
center : end_center ,
radius : radius ,
angle : end_angle ,
} ,
} ;
} )
}
/// left straight right route
pub fn lsr ( radius : f64 , end_point : Point , end_angle : Angle ) -> Result < Self , Error > {
let start_center = Point ::new ( - radius , 0.0 ) ;
// 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 . center = end . origin
+ Rotation ::new ( end . angle)
let end_center = end_point
+ Rotation ::new ( end _ angle)
. inverse ( )
. transform_vector ( Vector 2D::new ( end . magnitude , 0.0 ) ) ;
. transform_vector ( Vector ::new ( radius , 0.0 ) ) ;
// check if inside tangent can even be constructed
if ( ( route_csc . end . center . x - route_csc . start . center . x ) . powi ( 2 )
+ ( route_csc . end . center . y - route_csc . start . center . y ) . powi ( 2 ) )
. sqrt ( )
< 2.0 * end . magnitude
if ( ( end_center . x - start_center . x ) . powi ( 2 ) + ( end_center . y - start_center . y ) . powi ( 2 ) )
. sqrt ( )
< 2.0 * radius
{
return Err ( Error ::CirclesTooClose ) ;
}
// get the tangent length via some simple trigonometry
route_csc . tangent . magnitude = ( ( route_csc . end . center . x - route_csc . start . center. x ) . powi ( 2 )
+ ( route_csc. end . center . y - route_csc . start . center. y ) . powi ( 2 )
- ( 2.0 * end. magnitude ) . powi ( 2 ) )
let tangent_magnitude = ( ( end_center . x - start_ center. x ) . powi ( 2 )
+ ( end_center. y - start_ center. y ) . powi ( 2 )
- ( 2.0 * radius ) . powi ( 2 ) )
. sqrt ( ) ;
// tangent middle is the same as the middle of the straight from the center of the start
let tangent_middle = route_csc. end . center . lerp ( route_csc . start . center, 0.5 ) ;
let tangent_middle = end_center. lerp ( start_ center, 0.5 ) ;
// get the tangent angle
route_csc . tangent . angle = Angle ::radians (
( ( route_csc . end . center . y - tangent_middle . y )
/ ( route_csc . end . center . x - tangent_middle . x ) )
. atan ( )
+ ( 2.0 * end . magnitude / route_csc . tangent . magnitude ) . atan ( ) ,
let mut tangent_angle = Angle ::radians (
( ( end_center . y - tangent_middle . y ) / ( end_center . x - tangent_middle . x ) ) . atan ( )
+ ( 2.0 * radius / tangent_magnitude ) . atan ( ) ,
) ;
// if the end circle center x value is smaller than the
// start circle center x value
// the angle would rotated by π so to prevent that:
if route_csc. end . center . x < route_csc . start . center. x {
route_csc. tangent . angle + = Angle ::pi ( ) ;
if end_center. x < start_ center. x {
tangent_ angle + = Angle ::pi ( ) ;
}
// get the angle of the start circle
route_csc . start . angle = ( route_csc . tangent . angle - Angle ::frac_pi_2 ( ) ) . positive ( ) ;
let start_angle = ( tangent_ angle - Angle ::frac_pi_2 ( ) ) . positive ( ) ;
// get the tangent origin by moving the vector from the start circle center
// π/2 to it's own direction and the magnitude of the circle radius
route_csc . tangent . origin = route_csc . start . center
+ Rotation ::new ( route_csc . start . angle )
. transform_vector ( Vector2D ::new ( route_csc . start . radius , 0.0 ) ) ;
let tangent_origin =
start_center + Rotation ::new ( start_angle ) . transform_vector ( Vector ::new ( 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 ( ) ;
let end_angle = ( ( Angle ::frac_pi_2 ( ) - end_angle ) - tangent_angle ) . positive ( ) ;
Ok ( route_csc )
Ok ( Self {
start : CirclePath {
center : start_center ,
radius : radius ,
angle : start_angle ,
} ,
tangent : StraightPath {
origin : tangent_origin ,
vector : Vector ::from_angle_and_length ( tangent_angle , tangent_magnitude ) ,
} ,
end : CirclePath {
center : end_center ,
radius : radius ,
angle : end_angle ,
} ,
} )
}
/// get the length of the path
pub fn get_length ( & self ) -> f64 {
self . start . get_length ( ) + self . tangent . magnitude + self . end . get_length ( )
self . start . get_length ( ) + self . tangent . vector. length ( ) + self . end . get_length ( )
}
/// get the shortest circle straight circle route
pub fn get_shortest ( end : Vector ) -> Result < Self , Error > {
pub fn get_shortest ( radius: f64 , end_point : Point , end_angle : Angle ) -> Result < Self , Error > {
let mut route_csc ;
let route_rsr = Self ::rsr ( end ) . unwrap ( ) ;
let route_lsl = Self ::rsr ( end ) . unwrap ( ) ;
let route_lsr = Self ::rsr ( end ) ;
let route_rsl = Self ::rsr ( end ) ;
let route_rsr = Self ::rsr ( radius, end_point, end_angle ) . unwrap ( ) ;
let route_lsl = Self ::rsr ( radius, end_point, end_angle ) . unwrap ( ) ;
let route_lsr = Self ::rsr ( radius, end_point, end_angle ) ;
let route_rsl = Self ::rsr ( radius, end_point, end_angle ) ;
route_csc = route_rsr ;
if route_lsl . get_length ( ) < route_csc . get_length ( ) {
@ -430,181 +394,161 @@ impl RouteCSC {
/// Route with 3 Circles
impl RouteCCC {
/// right left right route (not working yet)
pub fn rlr ( end : Vector ) -> Result < Self , Error > {
let mut route_ccc = RouteCCC {
start : CircleVector {
center : Point ::new ( end . magnitude , 0.0 ) ,
radius : end . magnitude ,
angle : Angle ::zero ( ) ,
} ,
middle : CircleVector {
center : Point ::zero ( ) ,
radius : end . magnitude ,
angle : Angle ::zero ( ) ,
} ,
end : CircleVector {
center : Point ::zero ( ) ,
radius : end . magnitude ,
angle : Angle ::zero ( ) ,
} ,
} ;
pub fn rlr ( radius : f64 , end_point : Point , end_angle : Angle ) -> Result < Self , Error > {
let start_center = Point ::new ( radius , 0.0 ) ;
// 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 we use the inverse end.angle)
route_ccc . end . center = end . origin
+ Rotation ::new ( end . angle)
let end_center = end_point
+ Rotation ::new ( end_angle )
. inverse ( )
. transform_vector ( Vector 2D::new ( end . magnitude , 0.0 ) ) ;
. transform_vector ( Vector ::new ( radius , 0.0 ) ) ;
// check if path can be constructed or if the circles are too far apart
if ( ( route_ccc . end . center . x - route_ccc . start . center . x ) . powi ( 2 )
+ ( route_ccc . end . center . y - route_ccc . start . center . y ) . powi ( 2 ) )
. sqrt ( )
> ( 4.0 * end . magnitude )
if ( ( end_center . x - start_center . x ) . powi ( 2 ) + ( end_center . y - start_center . y ) . powi ( 2 ) )
. sqrt ( )
> ( 4.0 * radius )
{
return Err ( Error ::CirclesTooFarApart ) ;
}
let vector_start_center_middle_center : Vector2D ;
route_ccc . middle . center = {
let vector_start_center_end_center = Vector2D ::new (
route_ccc . end . center . x - route_ccc . start . center . x ,
route_ccc . end . center . y - route_ccc . start . center . y ,
) ;
let vector_start_center_middle_center : Vector ;
let vector_start_center_end_center_magnitude =
( vector_start_center_end_center . x . powi ( 2 )
+ vector_start_center_end_center . y . powi ( 2 ) )
. sqrt ( ) ;
let middle_center = {
let vector_start_center_end_center =
Vector ::new ( end_center . x - start_center . x , end_center . y - start_center . y ) ;
let vector_start_center_middle_center_angle =
vector_start_center_end_center . angle_from_x_axis ( ) . radians
+ ( vector_start_center_end_center _magnitude / ( 4.0 * end . magnitude ) ) . acos ( ) ;
+ ( vector_start_center_end_center . length ( ) / ( 4.0 * radius ) ) . acos ( ) ;
vector_start_center_middle_center = Vector 2D ::new (
( 2.0 * end. magnitude ) * vector_start_center_middle_center_angle . cos ( ) ,
( 2.0 * end. magnitude ) * vector_start_center_middle_center_angle . sin ( ) ,
vector_start_center_middle_center = Vector ::new (
( 2.0 * radius ) * vector_start_center_middle_center_angle . cos ( ) ,
( 2.0 * radius ) * vector_start_center_middle_center_angle . sin ( ) ,
) ;
Point ::new (
route_ccc. start . center. x + vector_start_center_middle_center . x ,
route_ccc. start . center. y + vector_start_center_middle_center . y ,
start_ center. x + vector_start_center_middle_center . x ,
start_ center. y + vector_start_center_middle_center . y ,
)
} ;
let vector_middle_center_end_center = Vector 2D ::new (
route_ccc. end . center . x - route_ccc . middle . center. x ,
route_ccc. end . center . y - route_ccc . middle . center. y ,
let vector_middle_center_end_center = Vector ::new (
end_center. x - middle_ center. x ,
end_center. y - middle_ center. y ,
) ;
route_ccc . start . angle =
let start_ angle =
( Angle ::pi ( ) - vector_start_center_middle_center . angle_from_x_axis ( ) ) . positive ( ) ;
route_ccc . middle . angle = Rotation ::new ( Angle ::pi ( ) )
let middle_ angle = Rotation ::new ( Angle ::pi ( ) )
. transform_vector ( vector_start_center_middle_center )
. angle_to ( vector_middle_center_end_center )
. positive ( ) ;
route_ccc . end . angle = Rotation ::new ( Angle ::pi ( ) )
let end_ angle = Rotation ::new ( Angle ::pi ( ) )
. transform_vector ( vector_middle_center_end_center )
. angle_to ( Vector 2D ::new (
end . origin . x - route_ccc . end . center. x ,
end . origin . y - route_ccc . end . center. y ,
. angle_to ( Vector ::new (
end _point. x - end_ center. x ,
end _point. y - end_ center. y ,
) )
. positive ( ) ;
Ok ( route_ccc )
}
/// left right left route (not working yet)
pub fn lrl ( end : Vector ) -> Result < Self , Error > {
let mut route_ccc = RouteCCC {
start : CircleVector {
center : Point ::new ( - end . magnitude , 0.0 ) ,
radius : end . magnitude ,
angle : Angle ::zero ( ) ,
Ok ( Self {
start : CirclePath {
center : start_center ,
radius : radius ,
angle : start_angle ,
} ,
middle : Circle Vector {
center : Point::zero ( ) ,
radius : end. magnitude ,
angle : Angle::zero ( ) ,
middle : CirclePath {
center : middle_center ,
radius : radius ,
angle : middle_angle ,
} ,
end : Circle Vector {
center : Point::zero ( ) ,
radius : end. magnitude ,
angle : Angle::zero ( ) ,
end : Circle Path {
center : end_center ,
radius : radius ,
angle : end_angle ,
} ,
} ;
} )
}
/// left right left route (not working yet)
pub fn lrl ( radius : f64 , end_point : Point , end_angle : Angle ) -> Result < Self , Error > {
let start_center = Point ::new ( - radius , 0.0 ) ;
// get the center point by adding the end vector to the end 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_ccc . end . center = end . origin
+ Rotation ::new ( Angle ::pi ( ) - end . angle )
. transform_vector ( Vector2D ::new ( end . magnitude , 0.0 ) ) ;
let end_center = end_point
+ Rotation ::new ( Angle ::pi ( ) - end_angle ) . transform_vector ( Vector ::new ( radius , 0.0 ) ) ;
// check if path can be constructed or if the circles are too far apart
if ( ( route_ccc . end . center . x - route_ccc . start . center . x ) . powi ( 2 )
+ ( route_ccc . end . center . y - route_ccc . start . center . y ) . powi ( 2 ) )
. sqrt ( )
> ( 4.0 * end . magnitude )
if ( ( end_center . x - start_center . x ) . powi ( 2 ) + ( end_center . y - start_center . y ) . powi ( 2 ) )
. sqrt ( )
> ( 4.0 * radius )
{
return Err ( Error ::CirclesTooFarApart ) ;
}
let vector_start_center_middle_center : Vector 2D ;
let vector_start_center_middle_center : Vector ;
route_ccc . middle . center = {
let vector_start_center_end_center = Vector2D ::new (
route_ccc . end . center . x - route_ccc . start . center . x ,
route_ccc . end . center . y - route_ccc . start . center . y ,
) ;
let vector_start_center_end_center_magnitude =
( vector_start_center_end_center . x . powi ( 2 )
+ vector_start_center_end_center . y . powi ( 2 ) )
. sqrt ( ) ;
let middle_center = {
let vector_start_center_end_center =
Vector ::new ( end_center . x - start_center . x , end_center . y - start_center . y ) ;
let vector_start_center_middle_center_angle =
vector_start_center_end_center . angle_from_x_axis ( ) . radians
- ( vector_start_center_end_center _magnitude / ( 4.0 * end . magnitude ) ) . acos ( ) ;
- ( vector_start_center_end_center . length ( ) / ( 4.0 * radius ) ) . acos ( ) ;
vector_start_center_middle_center = Vector 2D ::new (
( 2.0 * end. magnitude ) * vector_start_center_middle_center_angle . cos ( ) ,
( 2.0 * end. magnitude ) * vector_start_center_middle_center_angle . sin ( ) ,
vector_start_center_middle_center = Vector ::new (
( 2.0 * radius ) * vector_start_center_middle_center_angle . cos ( ) ,
( 2.0 * radius ) * vector_start_center_middle_center_angle . sin ( ) ,
) ;
Point ::new (
route_ccc. start . center. x + vector_start_center_middle_center . x ,
route_ccc. start . center. y + vector_start_center_middle_center . y ,
start_ center. x + vector_start_center_middle_center . x ,
start_ center. y + vector_start_center_middle_center . y ,
)
} ;
let vector_middle_center_end_center = Vector 2D ::new (
route_ccc. end . center . x - route_ccc . middle . center. x ,
route_ccc. end . center . y - route_ccc . middle . center. y ,
let vector_middle_center_end_center = Vector ::new (
end_center. x - middle_ center. x ,
end_center. y - middle_ center. y ,
) ;
route_ccc . start . angle = ( vector_start_center_middle_center . angle_from_x_axis ( ) ) . positive ( ) ;
let start_ angle = ( vector_start_center_middle_center . angle_from_x_axis ( ) ) . positive ( ) ;
route_ccc . middle . angle = vector_middle_center_end_center
let middle_ angle = vector_middle_center_end_center
. angle_to (
Rotation ::new ( Angle ::pi ( ) ) . transform_vector ( vector_start_center_middle_center ) ,
)
. positive ( ) ;
route_ccc . end . angle = Vector2D ::new (
end . origin . x - route_ccc . end . center . x ,
end . origin . y - route_ccc . end . center . y ,
)
. angle_to ( Rotation ::new ( Angle ::pi ( ) ) . transform_vector ( vector_middle_center_end_center ) )
. positive ( ) ;
let end_angle = Vector ::new ( end_point . x - end_center . x , end_point . y - end_center . y )
. angle_to ( Rotation ::new ( Angle ::pi ( ) ) . transform_vector ( vector_middle_center_end_center ) )
. positive ( ) ;
Ok ( route_ccc )
Ok ( Self {
start : CirclePath {
center : start_center ,
radius : radius ,
angle : start_angle ,
} ,
middle : CirclePath {
center : middle_center ,
radius : radius ,
angle : middle_angle ,
} ,
end : CirclePath {
center : end_center ,
radius : radius ,
angle : end_angle ,
} ,
} )
}
/// get the length of the path
@ -613,9 +557,9 @@ impl RouteCCC {
}
/// get the shortest circle circle circle route
pub fn get_shortest ( end: Vector ) -> Result < Self , Error > {
let route_rlr = Self ::rlr ( end) ;
let route_lrl = Self ::lrl ( end) ;
pub fn get_shortest ( radius: f64 , end_point : Point , end_angle : Angle ) -> Result < Self , Error > {
let route_rlr = Self ::rlr ( radius, end_point, end_angle ) ;
let route_lrl = Self ::lrl ( radius, end_point, end_angle ) ;
if let Ok ( route_rlr ) = route_rlr {
if let Ok ( route_lrl ) = route_lrl {
@ -636,9 +580,9 @@ impl RouteCCC {
}
/// get the shortest path
pub fn get_shortest ( end: Vector ) -> Path {
let route_csc = RouteCSC ::get_shortest ( end) . unwrap ( ) ;
let route_ccc = RouteCCC ::get_shortest ( end) ;
pub fn get_shortest ( radius: f64 , end_point : Point , end_angle : Angle ) -> Path {
let route_csc = RouteCSC ::get_shortest ( radius, end_point, end_angle ) . unwrap ( ) ;
let route_ccc = RouteCCC ::get_shortest ( radius, end_point, end_angle ) ;
if let Ok ( route_ccc ) = route_ccc {
if route_ccc . get_length ( ) < route_csc . get_length ( ) {
Path ::CCC ( route_ccc )