Skip to main content

geop_core_math/vector/
mod.rs

1pub mod linalg;
2
3use std::{
4    fmt::Display,
5    ops::{Index, IndexMut},
6};
7
8use crate::scalars::Scalar;
9
10#[derive(Debug, Clone, Copy, PartialEq)]
11pub struct Vector<S, const N: usize> {
12    data: [S; N],
13}
14
15pub type Vector4<S> = Vector<S, 4>;
16pub type Vector3<S> = Vector<S, 3>;
17pub type Vector2<S> = Vector<S, 2>;
18
19/// Type alias for backwards compatibility with older code.
20pub type VecN<S, const N: usize> = Vector<S, N>;
21
22impl<S: Default + Copy, const N: usize> Vector<S, N> {
23    pub fn new() -> Self {
24        Self {
25            data: [S::default(); N],
26        }
27    }
28
29    pub fn size(&self) -> usize {
30        N
31    }
32}
33
34impl<S: Scalar, const N: usize> Vector<S, N> {
35    pub fn from_array(data: [S; N]) -> Self {
36        Self { data }
37    }
38
39    /// Element access using a multi-index slice; only the first index is used
40    /// (vectors are 1-D).  Panics if `idx` is empty.
41    pub fn get(&self, idx: &[usize]) -> S {
42        self.data[idx[0]]
43    }
44}
45
46impl<S, const N: usize> Index<usize> for Vector<S, N> {
47    type Output = S;
48
49    fn index(&self, idx: usize) -> &Self::Output {
50        &self.data[idx]
51    }
52}
53
54impl<S: Default + Copy, const N: usize> IndexMut<usize> for Vector<S, N> {
55    fn index_mut(&mut self, idx: usize) -> &mut Self::Output {
56        &mut self.data[idx]
57    }
58}
59
60// swap xy
61impl<S: Scalar> Vector<S, 2> {
62    pub fn swap_xy(&self) -> Self {
63        Self::from_array([self[1], self[0]])
64    }
65}
66
67// zero
68impl<S: Scalar, const N: usize> Vector<S, N> {
69    pub fn zero() -> Self {
70        Self { data: [S::ZERO; N] }
71    }
72
73    /// Every component set to [`Scalar::ENTIRE`] — `could_be_equal`s any
74    /// other vector of the same dimension componentwise.
75    pub fn everything() -> Self {
76        Self {
77            data: [S::ENTIRE; N],
78        }
79    }
80}
81
82impl<S: Scalar, const N: usize> Display for Vector<S, N> {
83    fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
84        write!(f, "Vector{}(", N)?;
85        for i in 0..N {
86            write!(f, "{}", self.data[i])?;
87            if i < N - 1 {
88                write!(f, ", ")?;
89            }
90        }
91        write!(f, ")")
92    }
93}
94
95/// Format a slice of vectors as `[v0, v1, ...]` — shared by the `Display`
96/// impls below (a plain `&[Vector<S, N>]` and a slice of those, e.g. a list
97/// of polygons/holes).
98fn fmt_vector_slice<T: Display>(items: &[T], f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
99    write!(f, "[")?;
100    for (i, v) in items.iter().enumerate() {
101        write!(f, "{v}")?;
102        if i + 1 < items.len() {
103            write!(f, ", ")?;
104        }
105    }
106    write!(f, "]")
107}
108
109/// A `Display`-only wrapper around `&[Vector<S, N>]` (or `&[Vec<Vector<S,
110/// N>>]`, via `VectorSlice(&Vec::from(...))`-style nesting) — `Display`
111/// can't be implemented directly on a foreign slice/`Vec` type, so callers
112/// wanting to print a slice of vectors (e.g. a boundary loop or polygon)
113/// go through this instead: `format!("{}", VectorSlice(&points))`.
114pub struct VectorSlice<'a, T>(pub &'a [T]);
115
116impl<'a, S: Scalar, const N: usize> Display for VectorSlice<'a, Vector<S, N>> {
117    fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
118        fmt_vector_slice(self.0, f)
119    }
120}
121
122impl<'a, S: Scalar, const N: usize> Display for VectorSlice<'a, Vec<Vector<S, N>>> {
123    fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
124        write!(f, "[")?;
125        for (i, v) in self.0.iter().enumerate() {
126            fmt_vector_slice(v, f)?;
127            if i + 1 < self.0.len() {
128                write!(f, ", ")?;
129            }
130        }
131        write!(f, "]")
132    }
133}
134
135// tests
136#[cfg(test)]
137mod tests {
138    use crate::scalars::{ScalInF64, Scalar};
139
140    use super::*;
141
142    #[test]
143    fn test_vector() {
144        let mut v = Vector::<ScalInF64, 3>::new();
145        v[0] = 1.into();
146        v[1] = 2.into();
147        v[2] = 3.into();
148
149        assert!(v[0].could_be_equal(1.into()));
150        assert!(v[1].could_be_equal(2.into()));
151        assert!(v[2].could_be_equal(3.into()));
152    }
153
154    #[test]
155    fn test_vector_everything() {
156        let v = Vector::<ScalInF64, 3>::everything();
157        assert!(v[0].could_be_equal(42.0.into()));
158        assert!(v[1].could_be_equal((-1e300).into()));
159        assert!(v[2].could_be_equal(0.into()));
160    }
161}