dynamics_spatial/
vector3d.rs1use nalgebra::Vector3;
4use std::ops::{Add, Mul, Neg, Sub};
5
6#[cfg(feature = "python")]
7use numpy::{PyReadonlyArrayDyn, ToPyArray, ndarray::Array1};
8#[cfg(feature = "python")]
9use pyo3::prelude::*;
10
11#[derive(Debug, Clone, Copy, PartialEq, Default)]
12pub struct Vector3D(pub(crate) Vector3<f64>);
14
15impl Vector3D {
16 #[must_use]
18 pub fn new(x: f64, y: f64, z: f64) -> Self {
19 Self(Vector3::new(x, y, z))
20 }
21
22 #[must_use]
24 pub fn zeros() -> Self {
25 Self(Vector3::zeros())
26 }
27
28 #[must_use]
29 pub fn as_slice(&self) -> &[f64; 3] {
30 self.0.as_slice().try_into().unwrap()
31 }
32
33 #[must_use]
35 pub fn norm(&self) -> f64 {
36 self.0.norm()
37 }
38
39 #[must_use]
41 pub fn x() -> Self {
42 Self(Vector3::x())
43 }
44
45 #[must_use]
47 pub fn y() -> Self {
48 Self(Vector3::y())
49 }
50
51 #[must_use]
53 pub fn z() -> Self {
54 Self(Vector3::z())
55 }
56
57 #[must_use]
59 pub fn cross(&self, other: &Vector3D) -> Vector3D {
60 Vector3D(self.0.cross(&other.0))
61 }
62
63 #[must_use]
64 #[cfg(feature = "python")]
65 pub fn to_numpy(&self, py: Python) -> Py<PyAny> {
67 Array1::from_iter(self.0.iter().copied())
68 .to_pyarray(py)
69 .into_any()
70 .unbind()
71 }
72
73 #[cfg(feature = "python")]
74 pub fn from_pyarray(array: &PyReadonlyArrayDyn<f64>) -> Result<Self, PyErr> {
79 let array = array.as_array();
80 if array.ndim() != 1 || array.len() != 3 {
81 return Err(PyErr::new::<pyo3::exceptions::PyValueError, _>(
82 "Input array must be one-dimensional with length 3.",
83 ));
84 }
85 Ok(Vector3D(Vector3::new(array[0], array[1], array[2])))
86 }
87
88 pub fn dot(&self, other: &Vector3D) -> f64 {
89 self.0.dot(&other.0)
90 }
91}
92
93impl Add for Vector3D {
94 type Output = Vector3D;
95
96 fn add(self, rhs: Self) -> Self::Output {
97 Vector3D(self.0 + rhs.0)
98 }
99}
100
101impl Sub for Vector3D {
102 type Output = Vector3D;
103
104 fn sub(self, rhs: Self) -> Self::Output {
105 Vector3D(self.0 - rhs.0)
106 }
107}
108
109impl Mul for Vector3D {
110 type Output = Vector3D;
111
112 fn mul(self, rhs: Self) -> Self::Output {
113 Vector3D(self.0.component_mul(&rhs.0))
114 }
115}
116
117impl Mul<f64> for Vector3D {
118 type Output = Vector3D;
119
120 fn mul(self, rhs: f64) -> Self::Output {
121 Vector3D(self.0 * rhs)
122 }
123}
124
125impl Mul<f64> for &Vector3D {
126 type Output = Vector3D;
127
128 fn mul(self, rhs: f64) -> Self::Output {
129 Vector3D(self.0 * rhs)
130 }
131}
132
133impl Mul<&Vector3D> for f64 {
134 type Output = Vector3D;
135
136 fn mul(self, rhs: &Vector3D) -> Self::Output {
137 Vector3D(rhs.0 * self)
138 }
139}
140
141impl Mul<Vector3D> for f64 {
142 type Output = Vector3D;
143
144 fn mul(self, rhs: Vector3D) -> Self::Output {
145 Vector3D(rhs.0 * self)
146 }
147}
148
149impl Neg for Vector3D {
150 type Output = Vector3D;
151
152 fn neg(self) -> Self::Output {
153 Vector3D(-self.0)
154 }
155}