sb_rust_library/
math.rs

1use std::ops::Range;
2
3/// A 2D vector over the reals.
4#[derive(Clone, Copy)]
5pub struct Vector {
6  /// x component of this vector.
7  pub x: f64,
8  /// y component of this vector.
9  pub y: f64,
10}
11
12/// A 2D point in real space.
13#[derive(Clone, Copy)]
14pub struct Point {
15  /// x coordinate of this point.
16  pub x: f64,
17  /// y coordinate of this point.
18  pub y: f64,
19}
20
21/// A rectangular region in a 2D vector space over a generic field.
22pub struct Bounds<T> {
23  /// Boundary of this region in the x-dimension.
24  pub x: Range<T>,
25  /// Boundary of this region in the y-dimension.
26  pub y: Range<T>
27}
28
29impl Vector {
30
31  /// Creates a new point struct.
32  pub fn new(x: f64, y: f64) -> Vector {
33    Vector { x, y }
34  }
35
36  /// Computes the norm of this vector.
37  pub fn norm(&self) -> f64 {
38    (self.x * self.x + self.y * self.y).sqrt()
39  }
40
41  /// Computes the 90 degree counterclockwise rotation of this vector.
42  pub fn rotate_ccw(&self) -> Vector {
43    (- self.y, self.x).into()
44  }
45
46  /// Computes the 90 degree clockwise rotation of this vector.
47  pub fn rotate_cw(&self) -> Vector {
48    ( self.y, -self.x).into()
49  }
50}
51
52impl Point {
53
54  /// Creates a new point struct.
55  pub fn new(x: f64, y: f64) -> Point {
56    Point { x, y }
57  }
58
59}
60
61impl<T> From<(Range<T>, Range<T>)> for Bounds<T> {
62  fn from((x, y): (Range<T>, Range<T>)) -> Self {
63    Bounds { x, y }
64  }
65}
66
67
68// Vector Addition
69
70impl std::ops::Add<Vector> for Vector {
71  type Output = Vector;
72
73  fn add(self, other: Self) -> Vector {
74    (self.x + other.x, self.y + other.y).into()
75  }
76}
77
78impl std::ops::Add<&Vector> for Vector {
79  type Output = Vector;
80
81  fn add(self, other: &Self) -> Vector {
82    (self.x + other.x, self.y + other.y).into()
83  }
84}
85
86impl std::ops::Add<Vector> for &Vector {
87  type Output = Vector;
88
89  fn add(self, other: Vector) -> Vector {
90    (self.x + other.x, self.y + other.y).into()
91  }
92}
93
94impl std::ops::Add<&Vector> for &Vector {
95  type Output = Vector;
96
97  fn add(self, other: &Vector) -> Vector {
98    (self.x + other.x, self.y + other.y).into()
99  }
100}
101
102impl std::ops::AddAssign<Vector> for Vector {
103  fn add_assign(&mut self, other: Self) {
104    self.x += other.x;
105    self.y += other.y;
106  }
107}
108
109impl std::ops::AddAssign<&Vector> for Vector {
110  fn add_assign(&mut self, other: &Self) {
111    self.x += other.x;
112    self.y += other.y;
113  }
114}
115
116// Vector Subtraction
117
118impl std::ops::Sub<Vector> for Vector {
119  type Output = Vector;
120
121  fn sub(self, other: Self) -> Vector {
122    (self.x - other.x, self.y - other.y).into()
123  }
124}
125
126impl std::ops::Sub<&Vector> for Vector {
127  type Output = Vector;
128
129  fn sub(self, other: &Self) -> Vector {
130    (self.x - other.x, self.y - other.y).into()
131  }
132}
133
134impl std::ops::Sub<Vector> for &Vector {
135  type Output = Vector;
136
137  fn sub(self, other: Vector) -> Vector {
138    (self.x - other.x, self.y - other.y).into()
139  }
140}
141
142impl std::ops::Sub<&Vector> for &Vector {
143  type Output = Vector;
144
145  fn sub(self, other: &Vector) -> Vector {
146    (self.x - other.x, self.y - other.y).into()
147  }
148}
149
150impl std::ops::SubAssign<Vector> for Vector {
151  fn sub_assign(&mut self, other: Self) {
152    self.x -= other.x;
153    self.y -= other.y;
154  }
155}
156
157impl std::ops::SubAssign<&Vector> for Vector {
158  fn sub_assign(&mut self, other: &Self) {
159    self.x -= other.x;
160    self.y -= other.y;
161  }
162}
163
164// Vector - Vector multiplication
165
166impl std::ops::Mul<Vector> for Vector {
167  type Output = f64;
168
169  fn mul(self, other: Self) -> f64 {
170    self.x * other.x + self.y * other.y
171  }
172}
173
174impl std::ops::Mul<Vector> for &Vector {
175  type Output = f64;
176
177  fn mul(self, other: Vector) -> f64 {
178    self.x * other.x + self.y * other.y
179  }
180}
181
182impl std::ops::Mul<&Vector> for Vector {
183  type Output = f64;
184
185  fn mul(self, other: &Self) -> f64 {
186    self.x * other.x + self.y * other.y
187  }
188}
189
190impl std::ops::Mul for &Vector {
191  type Output = f64;
192
193  fn mul(self, other: &Vector) -> f64 {
194    self.x * other.x + self.y * other.y
195  }
196}
197
198// Vector - Scalar Multiplication
199
200impl std::ops::Mul<f64> for Vector {
201  type Output = Vector;
202
203  fn mul(self, scalar: f64) -> Vector {
204    (self.x * scalar, self.y * scalar).into()
205  }
206}
207
208impl std::ops::Mul<f64> for &Vector {
209  type Output = Vector;
210
211  fn mul(self, scalar: f64) -> Vector {
212    (self.x * scalar, self.y * scalar).into()
213  }
214}
215
216impl std::ops::Mul<Vector> for f64 {
217  type Output = Vector;
218
219  fn mul(self, p: Vector) -> Vector {
220    (self * p.x, self * p.y).into()
221  }
222}
223
224impl std::ops::Mul<&Vector> for f64 {
225  type Output = Vector;
226
227  fn mul(self, p: &Vector) -> Vector {
228    (self * p.x, self * p.y).into()
229  }
230}
231
232impl std::ops::MulAssign<f64> for Vector {
233  fn mul_assign(&mut self, scalar: f64) {
234    self.x *= scalar;
235    self.y *= scalar;
236  }
237}
238
239// Vector - Scalar Division
240
241impl std::ops::Div<f64> for Vector {
242  type Output = Vector;
243
244  fn div(self, scalar: f64) -> Vector {
245    (self.x / scalar, self.y / scalar).into()
246  }
247}
248
249impl std::ops::Div<f64> for &Vector {
250  type Output = Vector;
251
252  fn div(self, scalar: f64) -> Vector {
253    (self.x / scalar, self.y / scalar).into()
254  }
255}
256
257impl std::ops::DivAssign<f64> for Vector {
258  fn div_assign(&mut self, scalar: f64) {
259    self.x /= scalar;
260    self.y /= scalar;
261  }
262}
263
264// Negation
265
266impl std::ops::Neg for Vector {
267  type Output = Vector;
268
269  fn neg(self) -> Self {
270    (-self.x, -self.y).into()
271  }
272}
273
274impl std::ops::Neg for &Vector {
275  type Output = Vector;
276
277  fn neg(self) -> Vector {
278    (-self.x, -self.y).into()
279  }
280}
281
282// Point - Point Subtraction
283
284impl std::ops::Sub<Point> for Point {
285  type Output = Vector;
286
287  fn sub(self, other: Self) -> Vector {
288    (self.x - other.x, self.y - other.y).into()
289  }
290}
291
292impl std::ops::Sub<&Point> for Point {
293  type Output = Vector;
294
295  fn sub(self, other: &Self) -> Vector {
296    (self.x - other.x, self.y - other.y).into()
297  }
298}
299
300impl std::ops::Sub<Point> for &Point {
301  type Output = Vector;
302
303  fn sub(self, other: Point) -> Vector {
304    (self.x - other.x, self.y - other.y).into()
305  }
306}
307
308impl std::ops::Sub<&Point> for &Point {
309  type Output = Vector;
310
311  fn sub(self, other: &Point) -> Vector {
312    (self.x - other.x, self.y - other.y).into()
313  }
314}
315
316// Point-Vector Addition
317
318impl std::ops::Add<Vector> for Point {
319  type Output = Point;
320
321  fn add(self, other: Vector) -> Point {
322    (self.x + other.x, self.y + other.y).into()
323  }
324}
325
326impl std::ops::Add<&Vector> for Point {
327  type Output = Point;
328
329  fn add(self, other: &Vector) -> Point {
330    (self.x + other.x, self.y + other.y).into()
331  }
332}
333
334impl std::ops::Add<Vector> for &Point {
335  type Output = Point;
336
337  fn add(self, other: Vector) -> Point {
338    (self.x + other.x, self.y + other.y).into()
339  }
340}
341
342impl std::ops::Add<&Vector> for &Point {
343  type Output = Point;
344
345  fn add(self, other: &Vector) -> Point {
346    (self.x + other.x, self.y + other.y).into()
347  }
348}
349
350impl std::ops::AddAssign<Vector> for Point {
351  fn add_assign(&mut self, other: Vector) {
352    self.x += other.x;
353    self.y += other.y;
354  }
355}
356
357impl std::ops::AddAssign<&Vector> for Point {
358  fn add_assign(&mut self, other: &Vector) {
359    self.x += other.x;
360    self.y += other.y;
361  }
362}
363
364
365// Conversion operations
366
367impl From<(f64, f64)> for Vector {
368  fn from((x, y): (f64, f64)) -> Self {
369    Vector { x, y }
370  }
371}
372
373impl From<Vector> for (f64, f64) {
374  fn from(p: Vector) -> Self {
375    (p.x, p.y)
376  }
377}
378
379impl From<&Vector> for (f64, f64) {
380  fn from(p: &Vector) -> Self {
381    (p.x, p.y)
382  }
383}
384
385impl From<(f64, f64)> for Point {
386  fn from((x, y): (f64, f64)) -> Self {
387    Point { x, y }
388  }
389}
390
391impl From<Point> for (f64, f64) {
392  fn from(p: Point) -> Self {
393    (p.x, p.y)
394  }
395}
396
397impl From<&Point> for (f64, f64) {
398  fn from(p: &Point) -> Self {
399    (p.x, p.y)
400  }
401}
402
403impl From<Point> for Vector {
404  fn from(p: Point) -> Self {
405    Vector { x: p.x, y: p.y }
406  }
407}
408
409impl From<&Point> for Vector {
410  fn from(p: &Point) -> Self {
411    Vector { x: p.x, y: p.y }
412  }
413}
414
415impl From<Vector> for Point {
416  fn from(v: Vector) -> Self {
417    Point { x: v.x, y: v.y }
418  }
419}
420
421impl From<&Vector> for Point {
422  fn from(v: &Vector) -> Self {
423    Point { x: v.x, y: v.y }
424  }
425}
426
427/// Treats object mathematically as if it were a vector.
428///
429/// Basically this is a way to perform math on objects like `Vec<f64>` without
430/// wrapping them in a struct.
431///
432/// # Examples
433///
434/// Basic addition:
435/// ```
436/// let a = vec![1.0f64, 1.0, 1.0];
437/// let b = vec![1.0, 2.0, 3.0];
438/// let c = a.add(&b);
439/// assert_eq!(c, vec![2.0, 3.0, 4.0]);
440/// ```
441///
442/// Dot products:
443/// ```
444/// let a = vec![1.0, 1.0, 1.0];
445/// let b = vec![1.0, 0.0, 2.0];
446/// assert_eq!(a.dot(b), 4.0);
447/// ```
448pub trait VectorMath: Sized {
449  /// Computes dot product of two vectors.
450  fn dot(&self, other: &Self) -> f64;
451
452  /// Adds two vectors, returning a new vector.
453  fn add(&self, other: &Self) -> Self;
454
455  /// Subtracts two vectors, returning a new vector.
456  fn sub(&self, other: &Self) -> Self;
457
458  /// Multiplies a scalar and a vector, returning a new vector.
459  fn mul(&self, scalar: f64) -> Self;
460
461  /// Multiplies a vector and a vector pointwise, returning a new vector.
462  fn mul_pt(&self, other: &Self) -> Self;
463
464  /// Computes the vector norm
465  fn norm(&self) -> f64 {
466    self.dot(self).sqrt()
467  }
468
469  /// Normalizes the vector to unit length, returning a new vector
470  fn normalized(&self) -> Self {
471    self.mul(1.0 / self.norm())
472  }
473}
474
475impl VectorMath for Vec<f64> {
476  fn dot(&self, other: &Self) -> f64 {
477    self.iter().zip(other.iter()).map(|(x, y)| x * y).sum::<f64>()
478  }
479  fn add(&self, other: &Self) -> Self {
480    self.iter().zip(other.iter()).map(|(x, y)| x + y).collect()
481  }
482  fn sub(&self, other: &Self) -> Self {
483    self.iter().zip(other.iter()).map(|(x, y)| x - y).collect()
484  }
485  fn mul(&self, scalar: f64) -> Self {
486    self.iter().map(|x| scalar * x).collect()
487  }
488  fn mul_pt(&self, other: &Self) -> Self {
489    self.iter().zip(other.iter()).map(|(x, y)| x * y).collect()
490  }
491}
492
493impl VectorMath for (f64, f64) {
494  fn dot(&self, other: &Self) -> f64 {
495    self.0 * other.0 + self.1 * other.1
496  }
497  fn add(&self, other: &Self) -> Self {
498    (self.0 + other.0, self.1 + other.1)
499  }
500  fn sub(&self, other: &Self) -> Self {
501    (self.0 - other.0, self.1 - other.1)
502  }
503  fn mul(&self, scalar: f64) -> Self {
504    (scalar * self.0, scalar * self.1)
505  }
506  fn mul_pt(&self, other: &Self) -> Self {
507    (self.0 * other.0, self.1 * other.1)
508  }
509}