box2d_rust/math_functions/
vector.rs1use super::*;
5
6pub fn compute_rotation_between_unit_vectors(v1: Vec2, v2: Vec2) -> Rot {
8 debug_assert!(abs_float(1.0 - length(v1)) < 100.0 * f32::EPSILON);
9 debug_assert!(abs_float(1.0 - length(v2)) < 100.0 * f32::EPSILON);
10
11 let rot = Rot {
12 c: dot(v1, v2),
13 s: cross(v1, v2),
14 };
15 normalize_rot(rot)
16}
17
18pub fn dot(a: Vec2, b: Vec2) -> f32 {
20 a.x * b.x + a.y * b.y
21}
22
23pub fn cross(a: Vec2, b: Vec2) -> f32 {
25 a.x * b.y - a.y * b.x
26}
27
28pub fn cross_vs(v: Vec2, s: f32) -> Vec2 {
30 Vec2 {
31 x: s * v.y,
32 y: -s * v.x,
33 }
34}
35
36pub fn cross_sv(s: f32, v: Vec2) -> Vec2 {
38 Vec2 {
39 x: -s * v.y,
40 y: s * v.x,
41 }
42}
43
44pub fn left_perp(v: Vec2) -> Vec2 {
46 Vec2 { x: -v.y, y: v.x }
47}
48
49pub fn right_perp(v: Vec2) -> Vec2 {
51 Vec2 { x: v.y, y: -v.x }
52}
53
54pub fn add(a: Vec2, b: Vec2) -> Vec2 {
56 Vec2 {
57 x: a.x + b.x,
58 y: a.y + b.y,
59 }
60}
61
62pub fn sub(a: Vec2, b: Vec2) -> Vec2 {
64 Vec2 {
65 x: a.x - b.x,
66 y: a.y - b.y,
67 }
68}
69
70pub fn neg(a: Vec2) -> Vec2 {
72 Vec2 { x: -a.x, y: -a.y }
73}
74
75pub fn lerp(a: Vec2, b: Vec2, t: f32) -> Vec2 {
78 Vec2 {
79 x: (1.0 - t) * a.x + t * b.x,
80 y: (1.0 - t) * a.y + t * b.y,
81 }
82}
83
84pub fn mul(a: Vec2, b: Vec2) -> Vec2 {
86 Vec2 {
87 x: a.x * b.x,
88 y: a.y * b.y,
89 }
90}
91
92pub fn mul_sv(s: f32, v: Vec2) -> Vec2 {
94 Vec2 {
95 x: s * v.x,
96 y: s * v.y,
97 }
98}
99
100pub fn mul_add(a: Vec2, s: f32, b: Vec2) -> Vec2 {
102 Vec2 {
103 x: a.x + s * b.x,
104 y: a.y + s * b.y,
105 }
106}
107
108pub fn mul_sub(a: Vec2, s: f32, b: Vec2) -> Vec2 {
110 Vec2 {
111 x: a.x - s * b.x,
112 y: a.y - s * b.y,
113 }
114}
115
116pub fn abs(a: Vec2) -> Vec2 {
118 Vec2 {
119 x: abs_float(a.x),
120 y: abs_float(a.y),
121 }
122}
123
124pub fn min(a: Vec2, b: Vec2) -> Vec2 {
126 Vec2 {
127 x: min_float(a.x, b.x),
128 y: min_float(a.y, b.y),
129 }
130}
131
132pub fn max(a: Vec2, b: Vec2) -> Vec2 {
134 Vec2 {
135 x: max_float(a.x, b.x),
136 y: max_float(a.y, b.y),
137 }
138}
139
140pub fn clamp(v: Vec2, a: Vec2, b: Vec2) -> Vec2 {
142 Vec2 {
143 x: clamp_float(v.x, a.x, b.x),
144 y: clamp_float(v.y, a.y, b.y),
145 }
146}
147
148pub fn length(v: Vec2) -> f32 {
150 (v.x * v.x + v.y * v.y).sqrt()
151}
152
153pub fn distance(a: Vec2, b: Vec2) -> f32 {
155 let dx = b.x - a.x;
156 let dy = b.y - a.y;
157 (dx * dx + dy * dy).sqrt()
158}
159
160pub fn normalize(v: Vec2) -> Vec2 {
162 let length = (v.x * v.x + v.y * v.y).sqrt();
163 if length < f32::EPSILON {
164 return Vec2 { x: 0.0, y: 0.0 };
165 }
166
167 let inv_length = 1.0 / length;
168 Vec2 {
169 x: inv_length * v.x,
170 y: inv_length * v.y,
171 }
172}
173
174pub fn is_normalized(a: Vec2) -> bool {
176 let aa = dot(a, a);
177 abs_float(1.0 - aa) < 100.0 * f32::EPSILON
178}
179
180pub fn get_length_and_normalize(length: &mut f32, v: Vec2) -> Vec2 {
183 *length = (v.x * v.x + v.y * v.y).sqrt();
184 if *length < f32::EPSILON {
185 return Vec2 { x: 0.0, y: 0.0 };
186 }
187
188 let inv_length = 1.0 / *length;
189 Vec2 {
190 x: inv_length * v.x,
191 y: inv_length * v.y,
192 }
193}
194
195pub fn normalize_rot(q: Rot) -> Rot {
197 let mag = (q.s * q.s + q.c * q.c).sqrt();
198 let inv_mag = if mag > 0.0 { 1.0 / mag } else { 0.0 };
199 Rot {
200 c: q.c * inv_mag,
201 s: q.s * inv_mag,
202 }
203}
204
205pub fn integrate_rotation(q1: Rot, delta_angle: f32) -> Rot {
209 let q2 = Rot {
214 c: q1.c - delta_angle * q1.s,
215 s: q1.s + delta_angle * q1.c,
216 };
217 let mag = (q2.s * q2.s + q2.c * q2.c).sqrt();
218 let inv_mag = if mag > 0.0 { 1.0 / mag } else { 0.0 };
219 Rot {
220 c: q2.c * inv_mag,
221 s: q2.s * inv_mag,
222 }
223}
224
225pub fn length_squared(v: Vec2) -> f32 {
227 v.x * v.x + v.y * v.y
228}
229
230pub fn distance_squared(a: Vec2, b: Vec2) -> f32 {
232 let c = Vec2 {
233 x: b.x - a.x,
234 y: b.y - a.y,
235 };
236 c.x * c.x + c.y * c.y
237}