squid_n_core/geom/
vec3.rs1pub const ZERO_TOL: f64 = 1e-9;
15
16pub fn sub(a: [f64; 3], b: [f64; 3]) -> [f64; 3] {
18 [a[0] - b[0], a[1] - b[1], a[2] - b[2]]
19}
20
21pub fn add(a: [f64; 3], b: [f64; 3]) -> [f64; 3] {
23 [a[0] + b[0], a[1] + b[1], a[2] + b[2]]
24}
25
26pub fn scale(a: [f64; 3], s: f64) -> [f64; 3] {
28 [a[0] * s, a[1] * s, a[2] * s]
29}
30
31pub fn midpoint(a: [f64; 3], b: [f64; 3]) -> [f64; 3] {
33 [
34 0.5 * (a[0] + b[0]),
35 0.5 * (a[1] + b[1]),
36 0.5 * (a[2] + b[2]),
37 ]
38}
39
40pub fn dot(a: [f64; 3], b: [f64; 3]) -> f64 {
42 a[0] * b[0] + a[1] * b[1] + a[2] * b[2]
43}
44
45pub fn cross(a: [f64; 3], b: [f64; 3]) -> [f64; 3] {
47 [
48 a[1] * b[2] - a[2] * b[1],
49 a[2] * b[0] - a[0] * b[2],
50 a[0] * b[1] - a[1] * b[0],
51 ]
52}
53
54pub fn norm(a: [f64; 3]) -> f64 {
56 dot(a, a).sqrt()
57}
58
59pub fn dist(a: [f64; 3], b: [f64; 3]) -> f64 {
61 norm(sub(a, b))
62}
63
64pub fn unit(a: [f64; 3]) -> Option<[f64; 3]> {
66 let l = norm(a);
67 (l > ZERO_TOL).then(|| [a[0] / l, a[1] / l, a[2] / l])
68}
69
70pub fn unit_from(a: [f64; 3], b: [f64; 3]) -> Option<[f64; 3]> {
72 unit(sub(b, a))
73}
74
75#[cfg(test)]
76mod tests {
77 use super::*;
78
79 #[test]
80 fn dot_cross_norm_の基本則() {
81 let a = [1.0, 0.0, 0.0];
82 let b = [0.0, 2.0, 0.0];
83 assert_eq!(dot(a, b), 0.0);
84 assert_eq!(cross(a, b), [0.0, 0.0, 2.0]);
85 assert_eq!(norm(b), 2.0);
86 let c = cross(a, b);
88 assert_eq!(dot(c, a), 0.0);
89 assert_eq!(dot(c, b), 0.0);
90 }
91
92 #[test]
93 fn unit_は縮退ベクトルで_none_を返す() {
94 assert_eq!(unit([0.0, 0.0, 0.0]), None);
95 assert_eq!(unit([ZERO_TOL, 0.0, 0.0]), None);
96 assert_eq!(unit([0.0, 3.0, 4.0]), Some([0.0, 0.6, 0.8]));
97 }
98
99 #[test]
100 fn dist_と_midpoint() {
101 let a = [0.0, 0.0, 0.0];
102 let b = [3.0, 4.0, 0.0];
103 assert_eq!(dist(a, b), 5.0);
104 assert_eq!(midpoint(a, b), [1.5, 2.0, 0.0]);
105 assert_eq!(unit_from(a, b), Some([0.6, 0.8, 0.0]));
106 assert_eq!(unit_from(a, a), None);
107 }
108}