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::{Number, Scalar};
9
10#[derive(Debug, Clone, Copy, PartialEq)]
11pub struct Vector<const N: usize, T = Scalar> {
12    data: [T; N],
13}
14
15pub type Vector4<T = Scalar> = Vector<4, T>;
16pub type Vector3<T = Scalar> = Vector<3, T>;
17pub type Vector2<T = Scalar> = Vector<2, T>;
18
19impl<T: Default + Copy, const N: usize> Default for Vector<N, T> {
20    fn default() -> Self {
21        Self::new()
22    }
23}
24
25impl<T: Default + Copy, const N: usize> Vector<N, T> {
26    pub fn new() -> Self {
27        Self {
28            data: [T::default(); N],
29        }
30    }
31
32    pub fn size(&self) -> usize {
33        N
34    }
35}
36
37impl<T: Number, const N: usize> Vector<N, T> {
38    pub fn from_array(data: [T; N]) -> Self {
39        Self { data }
40    }
41
42    /// Its components, as an array.
43    pub fn to_array(&self) -> [T; N] {
44        self.data
45    }
46
47    /// Its components as plain numbers ([`Scalar::to_f64`], the midpoint):
48    /// for output and drawing, never for construction.
49    pub fn to_f64_array(&self) -> [f64; N] {
50        self.data.map(|x| x.to_f64())
51    }
52
53    /// Every component mapped by `f` — into dual numbers, say.
54    pub fn map<U: Number>(&self, f: impl Fn(T) -> U) -> Vector<N, U> {
55        Vector::from_array(self.data.map(f))
56    }
57
58    /// Element access using a multi-index slice; only the first index is used
59    /// (vectors are 1-D).  Panics if `idx` is empty.
60    pub fn get(&self, idx: &[usize]) -> T {
61        self.data[idx[0]]
62    }
63}
64
65impl<T, const N: usize> Index<usize> for Vector<N, T> {
66    type Output = T;
67
68    fn index(&self, idx: usize) -> &Self::Output {
69        &self.data[idx]
70    }
71}
72
73impl<T: Default + Copy, const N: usize> IndexMut<usize> for Vector<N, T> {
74    fn index_mut(&mut self, idx: usize) -> &mut Self::Output {
75        &mut self.data[idx]
76    }
77}
78
79// swap xy
80impl<T: Number> Vector<2, T> {
81    pub fn swap_xy(&self) -> Self {
82        Self::from_array([self[1], self[0]])
83    }
84}
85
86// zero
87impl<T: Number, const N: usize> Vector<N, T> {
88    pub fn zero() -> Self {
89        Self { data: [T::ZERO; N] }
90    }
91
92    /// The `k`-th coordinate axis: one at `k`, zero elsewhere.
93    pub fn axis(k: usize) -> Self {
94        let mut out = Self::zero();
95        out[k] = T::ONE;
96        out
97    }
98
99    /// The first `M` components — e.g. the Cartesian part `H` of a
100    /// homogeneous point `(H, w)`, which is *not* its position `H / w`.
101    pub fn head<const M: usize>(&self) -> Vector<M, T> {
102        Vector::from_array(std::array::from_fn(|k| self.data[k]))
103    }
104}
105
106impl<const N: usize> Vector<N> {
107    /// Every component set to [`Scalar::ENTIRE`] — `could_be_equal`s any
108    /// other vector of the same dimension componentwise.
109    pub fn everything() -> Self {
110        Self {
111            data: [Scalar::ENTIRE; N],
112        }
113    }
114
115    /// Componentwise [`Scalar::interpolate`]: `a` at `alpha=0`, `b` at
116    /// `alpha=1`. See that method's doc comment for why this beats a manual
117    /// `a*(1-alpha) + b*alpha` when components of `a`/`b` may coincide.
118    pub fn interpolate(a: &Self, b: &Self, alpha: Scalar) -> Self {
119        let mut out = Self::new();
120        for i in 0..a.size() {
121            out[i] = Scalar::interpolate(a[i], b[i], alpha);
122        }
123        out
124    }
125}
126
127impl<T: Number, const N: usize> Display for Vector<N, T> {
128    fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
129        write!(f, "Vector{}(", N)?;
130        for i in 0..N {
131            write!(f, "{}", self.data[i])?;
132            if i < N - 1 {
133                write!(f, ", ")?;
134            }
135        }
136        write!(f, ")")
137    }
138}
139
140/// Format a slice of vectors as `[v0, v1, ...]` — shared by the `Display`
141/// impls below (a plain `&[Vector<N, T>]` and a slice of those, e.g. a list
142/// of polygons/holes).
143fn fmt_vector_slice<T: Display>(items: &[T], f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
144    write!(f, "[")?;
145    for (i, v) in items.iter().enumerate() {
146        write!(f, "{v}")?;
147        if i + 1 < items.len() {
148            write!(f, ", ")?;
149        }
150    }
151    write!(f, "]")
152}
153
154/// A `Display`-only wrapper around `&[Vector<N, T>]` (or `&[Vec<Vector<T,
155/// N>>]`, via `VectorSlice(&Vec::from(...))`-style nesting) — `Display`
156/// can't be implemented directly on a foreign slice/`Vec` type, so callers
157/// wanting to print a slice of vectors (e.g. a boundary loop or polygon)
158/// go through this instead: `format!("{}", VectorSlice(&points))`.
159pub struct VectorSlice<'a, T>(pub &'a [T]);
160
161impl<'a, T: Number, const N: usize> Display for VectorSlice<'a, Vector<N, T>> {
162    fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
163        fmt_vector_slice(self.0, f)
164    }
165}
166
167impl<'a, T: Number, const N: usize> Display for VectorSlice<'a, Vec<Vector<N, T>>> {
168    fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
169        write!(f, "[")?;
170        for (i, v) in self.0.iter().enumerate() {
171            fmt_vector_slice(v, f)?;
172            if i + 1 < self.0.len() {
173                write!(f, ", ")?;
174            }
175        }
176        write!(f, "]")
177    }
178}
179
180/// A vector serializes as the array of its components' midpoints — how it
181/// travels to a viewer, which draws points, not enclosures — and reads back
182/// from an array of plain numbers, each a sharp scalar.
183impl<T: Number, const N: usize> serde::Serialize for Vector<N, T> {
184    fn serialize<Ser: serde::Serializer>(&self, serializer: Ser) -> Result<Ser::Ok, Ser::Error> {
185        use serde::ser::SerializeTuple;
186        let mut tuple = serializer.serialize_tuple(N)?;
187        for x in &self.data {
188            tuple.serialize_element(&x.to_f64())?;
189        }
190        tuple.end()
191    }
192}
193
194impl<'de, T: Number, const N: usize> serde::Deserialize<'de> for Vector<N, T> {
195    fn deserialize<D: serde::Deserializer<'de>>(deserializer: D) -> Result<Self, D::Error> {
196        struct Components<T, const N: usize>(std::marker::PhantomData<T>);
197
198        impl<'de, T: Number, const N: usize> serde::de::Visitor<'de> for Components<T, N> {
199            type Value = Vector<N, T>;
200
201            fn expecting(&self, f: &mut std::fmt::Formatter) -> std::fmt::Result {
202                write!(f, "an array of {N} numbers")
203            }
204
205            fn visit_seq<A: serde::de::SeqAccess<'de>>(
206                self,
207                mut seq: A,
208            ) -> Result<Self::Value, A::Error> {
209                let mut out = Vector::zero();
210                for k in 0..N {
211                    let x: f64 = seq
212                        .next_element()?
213                        .ok_or_else(|| serde::de::Error::invalid_length(k, &self))?;
214                    out[k] = T::from_f64(x);
215                }
216                if seq.next_element::<serde::de::IgnoredAny>()?.is_some() {
217                    return Err(serde::de::Error::invalid_length(N + 1, &self));
218                }
219                Ok(out)
220            }
221        }
222
223        deserializer.deserialize_tuple(N, Components(std::marker::PhantomData))
224    }
225}
226
227// tests
228#[cfg(test)]
229mod tests {
230    use super::*;
231
232    #[test]
233    fn test_vector() {
234        let mut v = Vector::<3>::new();
235        v[0] = Scalar::from_i64(1);
236        v[1] = Scalar::from_i64(2);
237        v[2] = Scalar::from_i64(3);
238
239        assert!(v[0].could_be_equal(Scalar::from_i64(1)));
240        assert!(v[1].could_be_equal(Scalar::from_i64(2)));
241        assert!(v[2].could_be_equal(Scalar::from_i64(3)));
242    }
243
244    #[test]
245    fn test_vector_everything() {
246        let v = Vector::<3>::everything();
247        assert!(v[0].could_be_equal(Scalar::from_f64(42.0)));
248        assert!(v[1].could_be_equal(Scalar::from_f64(-1e300)));
249        assert!(v[2].could_be_equal(Scalar::from_i64(0)));
250    }
251}