1use super::measurement::*;
4
5pub const POUNDS_PER_NEWTON: f64 = 0.224809;
7pub const POUNDALS_PER_NEWTON: f64 = 7.2330;
10pub const KILOPONDS_PER_NEWTON: f64 = 1.0 / 9.80665;
12pub const DYNES_PER_NEWTON: f64 = 1e5;
14
15#[cfg_attr(feature = "serde", derive(serde::Serialize, serde::Deserialize))]
32#[derive(Copy, Clone, Debug, Default)]
33pub struct Force {
34 newtons: f64,
35}
36
37impl Force {
38 pub fn from_newtons(newtons: f64) -> Self {
40 Force { newtons }
41 }
42
43 pub fn from_micronewtons(micronewtons: f64) -> Self {
45 Self::from_newtons(micronewtons / 1e6)
46 }
47
48 pub fn from_millinewtons(millinewtons: f64) -> Self {
50 Self::from_newtons(millinewtons / 1e3)
51 }
52
53 pub fn from_pounds(pounds: f64) -> Self {
55 Self::from_newtons(pounds / POUNDS_PER_NEWTON)
56 }
57
58 pub fn from_poundals(poundals: f64) -> Self {
60 Self::from_newtons(poundals / POUNDALS_PER_NEWTON)
61 }
62
63 pub fn from_kiloponds(kiloponds: f64) -> Self {
65 Self::from_newtons(kiloponds / KILOPONDS_PER_NEWTON)
66 }
67
68 pub fn from_dynes(dynes: f64) -> Self {
70 Self::from_newtons(dynes / DYNES_PER_NEWTON)
71 }
72
73 pub fn as_micronewtons(&self) -> f64 {
75 self.newtons * 1e6
76 }
77
78 pub fn as_millinewtons(&self) -> f64 {
80 self.newtons * 1e3
81 }
82
83 pub fn as_newtons(&self) -> f64 {
85 self.newtons
86 }
87
88 pub fn as_pounds(&self) -> f64 {
90 self.newtons * POUNDS_PER_NEWTON
91 }
92
93 pub fn as_poundals(&self) -> f64 {
95 self.newtons * POUNDALS_PER_NEWTON
96 }
97
98 pub fn as_kiloponds(&self) -> f64 {
100 self.newtons * KILOPONDS_PER_NEWTON
101 }
102
103 pub fn as_dynes(&self) -> f64 {
105 self.newtons * DYNES_PER_NEWTON
106 }
107}
108
109impl Measurement for Force {
110 fn get_appropriate_units(&self) -> (&'static str, f64) {
111 let list = [
113 ("nN", 1e-9),
114 ("\u{00B5}N", 1e-6),
115 ("mN", 1e-3),
116 ("N", 1e0),
117 ("kN", 1e3),
118 ("MN", 1e6),
119 ("GN", 1e9),
120 ("TN", 1e12),
121 ];
122 self.pick_appropriate_units(&list)
123 }
124
125 fn get_base_units_name(&self) -> &'static str {
126 "N"
127 }
128
129 fn as_base_units(&self) -> f64 {
130 self.newtons
131 }
132
133 fn from_base_units(units: f64) -> Self {
134 Self::from_newtons(units)
135 }
136}
137
138implement_measurement! { Force }
139
140#[cfg(test)]
141mod test {
142 use crate::{force::*, test_utils::assert_almost_eq};
143
144 #[test]
145 pub fn newtons() {
146 let i1 = Force::from_newtons(100.0);
147 let r1 = i1.as_newtons();
148
149 assert_almost_eq(r1, 100.0);
150 }
151
152 #[test]
153 pub fn micronewtons() {
154 let i1 = Force::from_newtons(100.0);
155 let r1 = i1.as_micronewtons();
156
157 let i2 = Force::from_micronewtons(100.0);
158 let r2 = i2.as_newtons();
159
160 assert_almost_eq(r1, 1e8);
161 assert_almost_eq(r2, 1e-4);
162 }
163
164 #[test]
165 pub fn millinewtons() {
166 let i1 = Force::from_newtons(100.0);
167 let r1 = i1.as_millinewtons();
168
169 let i2 = Force::from_millinewtons(100.0);
170 let r2 = i2.as_newtons();
171
172 assert_almost_eq(r1, 1e5);
173 assert_almost_eq(r2, 1e-1);
174 }
175
176 #[test]
177 pub fn pounds() {
178 let i1 = Force::from_newtons(100.0);
179 let r1 = i1.as_pounds();
180
181 let i2 = Force::from_pounds(100.0);
182 let r2 = i2.as_newtons();
183
184 assert_almost_eq(r1, 22.480886300718);
185 assert_almost_eq(r2, 444.822);
186 }
187
188 #[test]
189 pub fn poundals() {
190 let i1 = Force::from_newtons(100.0);
191 let r1 = i1.as_poundals();
192
193 let i2 = Force::from_poundals(100.0);
194 let r2 = i2.as_newtons();
195
196 assert_almost_eq(r1, 723.3016238104);
197 assert_almost_eq(r2, 13.8255);
198 }
199
200 #[test]
201 pub fn kiloponds() {
202 let i1 = Force::from_newtons(100.0);
203 let r1 = i1.as_kiloponds();
204
205 let i2 = Force::from_kiloponds(100.0);
206 let r2 = i2.as_newtons();
207
208 assert_almost_eq(r1, 10.1972);
209 assert_almost_eq(r2, 980.665);
210 }
211
212 #[test]
213 pub fn dynes() {
214 let i1 = Force::from_newtons(100.0);
215 let r1 = i1.as_dynes();
216
217 let i2 = Force::from_dynes(100.0);
218 let r2 = i2.as_newtons();
219
220 assert_almost_eq(r1, 1e7);
221 assert_almost_eq(r2, 0.001);
222 }
223
224 #[test]
225 fn add() {
226 let a = Force::from_newtons(2.0);
227 let b = Force::from_newtons(4.0);
228 let c = a + b;
229 let d = b + a;
230 assert_almost_eq(c.as_newtons(), 6.0);
231 assert_eq!(c, d);
232 }
233
234 #[test]
235 fn sub() {
236 let a = Force::from_newtons(2.0);
237 let b = Force::from_newtons(4.0);
238 let c = a - b;
239 assert_almost_eq(c.as_newtons(), -2.0);
240 }
241
242 #[test]
243 fn mul() {
244 let a = Force::from_newtons(3.0);
245 let b = a * 2.0;
246 let c = 2.0 * a;
247 assert_almost_eq(b.as_newtons(), 6.0);
248 assert_eq!(b, c);
249 }
250
251 #[test]
252 fn div() {
253 let a = Force::from_newtons(2.0);
254 let b = Force::from_newtons(4.0);
255 let c = a / b;
256 let d = a / 2.0;
257 assert_almost_eq(c, 0.5);
258 assert_almost_eq(d.as_newtons(), 1.0);
259 }
260
261 #[test]
262 fn eq() {
263 let a = Force::from_newtons(2.0);
264 let b = Force::from_newtons(2.0);
265 assert_eq!(a == b, true);
266 }
267
268 #[test]
269 fn neq() {
270 let a = Force::from_newtons(2.0);
271 let b = Force::from_newtons(4.0);
272 assert_eq!(a == b, false);
273 }
274
275 #[test]
276 fn cmp() {
277 let a = Force::from_newtons(2.0);
278 let b = Force::from_newtons(4.0);
279 assert_eq!(a < b, true);
280 assert_eq!(a <= b, true);
281 assert_eq!(a > b, false);
282 assert_eq!(a >= b, false);
283 }
284}