nphysics2d/algebra/
force2.rs

1use na::storage::Storage;
2use na::{self, Isometry2, Point2, RealField, Vector, Vector1, Vector2, Vector3, U3};
3use std::mem;
4use std::ops::{Add, AddAssign, Mul, Neg, Sub, SubAssign};
5
6/// A force with a linear and angular (torque) component.
7#[repr(C)]
8#[derive(Copy, Clone, Debug)]
9pub struct Force2<N: RealField + Copy> {
10    /// The linear force.
11    pub linear: Vector2<N>,
12    /// The torque.
13    pub angular: N,
14}
15
16impl<N: RealField + Copy> Force2<N> {
17    /// Creates a force from its linear and angular components.
18    #[inline]
19    pub fn new(linear: Vector2<N>, angular: N) -> Self {
20        Force2 { linear, angular }
21    }
22
23    /// A zero force.
24    #[inline]
25    pub fn zero() -> Self {
26        Self::new(na::zero(), N::zero())
27    }
28
29    /// Create a force from a slice where the entries 0 and 1 are for the linear part and 2 for the angular part.
30    #[inline]
31    pub fn from_slice(data: &[N]) -> Self {
32        Self::new(Vector2::new(data[0], data[1]), data[2])
33    }
34
35    /// Create a force from a vector where the entries 0 and 1 are for the linear part and 2 for the angular part.
36    #[inline]
37    pub fn from_vector<S: Storage<N, U3>>(data: &Vector<N, U3, S>) -> Self {
38        Self::new(Vector2::new(data[0], data[1]), data[2])
39    }
40
41    /// Creates a force from its linear and angular components, both in vector form.
42    #[inline]
43    pub fn from_vectors(linear: Vector2<N>, angular: Vector1<N>) -> Self {
44        Self {
45            linear,
46            angular: angular.x,
47        }
48    }
49
50    /// Create a pure torque.
51    #[inline]
52    pub fn torque(torque: N) -> Self {
53        Self::new(na::zero(), torque)
54    }
55
56    /// Create a pure torque.
57    #[inline]
58    pub fn torque_from_vector(torque: Vector1<N>) -> Self {
59        Self::new(na::zero(), torque.x)
60    }
61
62    /// Create a pure linear force.
63    #[inline]
64    pub fn linear(linear: Vector2<N>) -> Self {
65        Self::new(linear, na::zero())
66    }
67
68    /// Creates the resultant of a linear force applied at the given point (relative to the center of mass).
69    #[inline]
70    pub fn linear_at_point(linear: Vector2<N>, point: &Point2<N>) -> Self {
71        Self::new(linear, point.coords.perp(&linear))
72    }
73
74    /// Creates the resultant of a torque applied at the given point (relative to the center of mass).
75    #[inline]
76    pub fn torque_at_point(torque: N, point: &Point2<N>) -> Self {
77        Self::new(point.coords * -torque, torque)
78    }
79
80    /// Creates the resultant of a torque applied at the given point (relative to the center of mass).
81    #[inline]
82    pub fn torque_from_vector_at_point(torque: Vector1<N>, point: &Point2<N>) -> Self {
83        Self::torque_at_point(torque.x, point)
84    }
85
86    /// The angular part of the force.
87    #[inline]
88    pub fn angular_vector(&self) -> Vector1<N> {
89        Vector1::new(self.angular)
90    }
91
92    /// Apply the given transformation to this force.
93    #[inline]
94    pub fn transform_by(&self, m: &Isometry2<N>) -> Self {
95        Self::new(m * self.linear, self.angular)
96    }
97
98    /// This force seen as a slice.
99    ///
100    /// The two first entries contain the linear part and the third entry contais the angular part.
101    #[inline]
102    pub fn as_slice(&self) -> &[N] {
103        self.as_vector().as_slice()
104    }
105
106    /// This force seen as a vector.
107    ///
108    /// The two first entries contain the linear part and the third entry contais the angular part.
109    #[inline]
110    pub fn as_vector(&self) -> &Vector3<N> {
111        unsafe { mem::transmute(self) }
112    }
113
114    /// This force seen as a mutable vector.
115    ///
116    /// The two first entries contain the linear part and the third entry contais the angular part.
117    #[inline]
118    pub fn as_vector_mut(&mut self) -> &mut Vector3<N> {
119        unsafe { mem::transmute(self) }
120    }
121}
122
123impl<N: RealField + Copy> Add<Force2<N>> for Force2<N> {
124    type Output = Self;
125
126    #[inline]
127    fn add(self, rhs: Self) -> Self {
128        Force2::new(self.linear + rhs.linear, self.angular + rhs.angular)
129    }
130}
131
132impl<N: RealField + Copy> AddAssign<Force2<N>> for Force2<N> {
133    #[inline]
134    fn add_assign(&mut self, rhs: Self) {
135        self.linear += rhs.linear;
136        self.angular += rhs.angular;
137    }
138}
139
140impl<N: RealField + Copy> Sub<Force2<N>> for Force2<N> {
141    type Output = Self;
142
143    #[inline]
144    fn sub(self, rhs: Self) -> Self {
145        Force2::new(self.linear - rhs.linear, self.angular - rhs.angular)
146    }
147}
148
149impl<N: RealField + Copy> SubAssign<Force2<N>> for Force2<N> {
150    #[inline]
151    fn sub_assign(&mut self, rhs: Self) {
152        self.linear -= rhs.linear;
153        self.angular -= rhs.angular;
154    }
155}
156
157impl<N: RealField + Copy> Mul<N> for Force2<N> {
158    type Output = Self;
159
160    #[inline]
161    fn mul(self, rhs: N) -> Self {
162        Force2::new(self.linear * rhs, self.angular * rhs)
163    }
164}
165
166impl<N: RealField + Copy> Neg for Force2<N> {
167    type Output = Self;
168
169    #[inline]
170    fn neg(self) -> Self {
171        Force2::new(-self.linear, -self.angular)
172    }
173}