src/cylinder.rs

changeset 40
1d865db9d3e4
parent 39
3d5c8ea1522c
child 41
56d609b70a3b
equal deleted inserted replaced
39:3d5c8ea1522c 40:1d865db9d3e4
43 #[derive(Copy, Clone, Debug, PartialEq, Serialize, Deserialize)] 43 #[derive(Copy, Clone, Debug, PartialEq, Serialize, Deserialize)]
44 pub struct CapPoint { 44 pub struct CapPoint {
45 pub r : f64, 45 pub r : f64,
46 pub angle : Angle 46 pub angle : Angle
47 } 47 }
48
49 /// Rotate input vector by angle φ.
50 #[inline]
51 fn rotate(φ : f64, Loc([x, y]) : Loc<f64, 2>) -> Loc<f64, 2> {
52 let sin_φ = φ.sin();
53 let cos_φ = φ.cos();
54 [cos_φ * x - sin_φ * y, sin_φ * x + cos_φ * y].into()
55 }
56
57 /// Mirror y coordinate of input vector.
58 #[inline]
59 fn ymirror(Loc([x, y]) : Loc<f64, 2>) -> Loc<f64, 2> {
60 [x, -y].into()
61 }
62
63 48
64 impl CapPoint { 49 impl CapPoint {
65 #[inline] 50 #[inline]
66 /// Convert to cylindrical coordinates given z coordinate 51 /// Convert to cylindrical coordinates given z coordinate
67 fn cyl_coords(&self, z : f64) -> CylCoords { 52 fn cyl_coords(&self, z : f64) -> CylCoords {
117 /// Convert tangent from side tangent to cap tangent 102 /// Convert tangent from side tangent to cap tangent
118 fn tangent_from_side(&self, top : bool, t : Tangent) -> Tangent { 103 fn tangent_from_side(&self, top : bool, t : Tangent) -> Tangent {
119 if top { 104 if top {
120 // The angle is such that down would be rotated to self.angle, counterclockwise 105 // The angle is such that down would be rotated to self.angle, counterclockwise
121 // The new tangent is R[down + t] - R[down] = Rt. 106 // The new tangent is R[down + t] - R[down] = Rt.
122 rotate(self.angle+f64::PI/2.0, t) 107 t.rotate(self.angle+f64::PI/2.0)
123 } else { 108 } else {
124 // The angle is such that up would be rotated to self.angle, clockwise 109 // The angle is such that up would be rotated to self.angle, clockwise
125 rotate(self.angle+f64::PI/2.0, ymirror(t)) 110 t.reflect_y().rotate(self.angle+f64::PI/2.0)
126 } 111 }
127 } 112 }
128 113
129 #[inline] 114 #[inline]
130 /// Convert tangent from cap tangent to tangent tangent 115 /// Convert tangent from cap tangent to tangent tangent
131 fn tangent_to_side(&self, top : bool, t : Tangent) -> Tangent { 116 fn tangent_to_side(&self, top : bool, t : Tangent) -> Tangent {
132 if top { 117 if top {
133 // The angle is such that self.angle would be rotated to down, clockwise 118 // The angle is such that self.angle would be rotated to down, clockwise
134 rotate(-self.angle-f64::PI/2.0, t) 119 t.rotate(-self.angle-f64::PI/2.0)
135 } else { 120 } else {
136 // The angle is such that self.angle would be rotated to up, counterclockwise 121 // The angle is such that self.angle would be rotated to up, counterclockwise
137 ymirror(rotate(-self.angle-f64::PI/2.0, t)) 122 t.rotate(-self.angle-f64::PI/2.0).reflect_y()
138 } 123 }
139 } 124 }
140 } 125 }
141 126
142 /// Coordinates on a side 127 /// Coordinates on a side
979 let angles = [0.0, π/2.0, π*5.0/6.0, π*7.0/5.0]; 964 let angles = [0.0, π/2.0, π*5.0/6.0, π*7.0/5.0];
980 965
981 for φ in angles { 966 for φ in angles {
982 let p = CYL.on_top(φ, CYL.radius / 2.0); 967 let p = CYL.on_top(φ, CYL.radius / 2.0);
983 let q_target = CYL.on_side(φ, CYL.height / 2.0); 968 let q_target = CYL.on_side(φ, CYL.height / 2.0);
984 let t = rotate(φ, [CYL.radius, 0.0].into()); 969 let t = Loc([CYL.radius, 0.0]).rotate(φ);
985 let t_target = Loc([0.0, -CYL.radius / 2.0]); 970 let t_target = Loc([0.0, -CYL.radius / 2.0]);
986 let (q, t_left) = CYL.partial_exp(p.point, t); 971 let (q, t_left) = CYL.partial_exp(p.point, t);
987 check_point_eq!(q, q_target.point); 972 check_point_eq!(q, q_target.point);
988 if let Some(t_left_) = t_left { 973 if let Some(t_left_) = t_left {
989 check_vec_eq!(t_left_, t_target); 974 check_vec_eq!(t_left_, t_target);
993 } 978 }
994 979
995 for φ in angles { 980 for φ in angles {
996 let p = CYL.on_top(φ + π/2.0, CYL.radius); 981 let p = CYL.on_top(φ + π/2.0, CYL.radius);
997 let q_target = CYL.on_side(φ, CYL.height / 2.0); 982 let q_target = CYL.on_side(φ, CYL.height / 2.0);
998 let t = 2.0 * rotate(φ, Loc([CYL.radius, -CYL.radius])); 983 let t = 2.0 * Loc([CYL.radius, -CYL.radius]).rotate(φ);
999 let t_target = Loc([-CYL.radius, -CYL.radius]); 984 let t_target = Loc([-CYL.radius, -CYL.radius]);
1000 let (q, t_left) = CYL.partial_exp(p.point, t); 985 let (q, t_left) = CYL.partial_exp(p.point, t);
1001 check_point_eq!(q, q_target.point); 986 check_point_eq!(q, q_target.point);
1002 if let Some(t_left_) = t_left { 987 if let Some(t_left_) = t_left {
1003 check_vec_eq!(t_left_, t_target); 988 check_vec_eq!(t_left_, t_target);
1012 let π = f64::PI; 997 let π = f64::PI;
1013 let angles = [0.0, π/2.0, π*5.0/6.0, π*7.0/5.0]; 998 let angles = [0.0, π/2.0, π*5.0/6.0, π*7.0/5.0];
1014 999
1015 for φ in angles { 1000 for φ in angles {
1016 let pt = CYL.on_top(φ, CYL.radius); 1001 let pt = CYL.on_top(φ, CYL.radius);
1017 let t = rotate(φ, Loc([0.1, 0.3])); 1002 let t = Loc([0.1, 0.3]).rotate(φ);
1018 let b = pt.clone().exp(&t); 1003 let b = pt.clone().exp(&t);
1019 let a = pt.exp(&(-t)); 1004 let a = pt.exp(&(-t));
1020 check_point_eq!(a.exp(&(2.0*t)).point, b.point); 1005 check_point_eq!(a.exp(&(2.0*t)).point, b.point);
1021 } 1006 }
1022 } 1007 }

mercurial