1pub mod bezier;
3pub mod math;
5pub mod rate_functions;
7use std::{
14 hash::{DefaultHasher, Hash, Hasher},
15 iter::Sum,
16 ops::Div,
17};
18
19use glam::{DVec3, Mat3, Vec2, Vec3, vec2, vec3};
20
21pub fn project(p: Vec3, unit_normal: Vec3) -> Vec3 {
23 p - unit_normal * unit_normal.dot(p)
24}
25
26pub fn generate_basis(unit_normal: Vec3) -> (Vec3, Vec3) {
28 let u = if unit_normal.x != 0.0 || unit_normal.y != 0.0 {
30 vec3(-unit_normal.y, unit_normal.x, 0.0)
31 } else {
32 vec3(1.0, 0.0, 0.0)
33 }
34 .normalize();
35 let v = unit_normal.cross(u).normalize();
36 (u, v)
37}
38
39pub fn convert_to_2d(p: Vec3, origin: Vec3, basis: (Vec3, Vec3)) -> Vec2 {
41 let p_local = p - origin;
43 vec2(basis.0.dot(p_local), basis.1.dot(p_local))
44}
45
46pub fn convert_to_3d(p: Vec2, origin: Vec3, basis: (Vec3, Vec3)) -> Vec3 {
48 origin + basis.0 * p.x + basis.1 * p.y
49}
50
51pub fn rotation_between_vectors(v1: Vec3, v2: Vec3) -> Mat3 {
53 if (v2 - v1).length() < f32::EPSILON {
56 return Mat3::IDENTITY;
57 }
58 let mut axis = v1.cross(v2);
59 if axis.length() < f32::EPSILON {
60 axis = v1.cross(Vec3::Y);
61 }
62 if axis.length() < f32::EPSILON {
63 axis = v1.cross(Vec3::Z);
64 }
65 let angle = angle_between_vectors(v1, v2);
68 Mat3::from_axis_angle(axis, angle)
70}
71
72pub fn avg<T: Clone + Sum + Div<f64, Output = T>>(data: &[T]) -> T {
74 data.iter().cloned().sum::<T>() / data.len() as f64
75}
76
77pub fn angle_between_vectors(v1: Vec3, v2: Vec3) -> f32 {
79 if v1.length() == 0.0 || v2.length() == 0.0 {
80 return 0.0;
81 }
82
83 (v1.dot(v2) / (v1.length() * v2.length()))
84 .clamp(-1.0, 1.0)
85 .acos()
86}
87
88pub fn resize_preserving_order<T: Clone>(vec: &[T], new_len: usize) -> Vec<T> {
90 let indices = (0..new_len).map(|i| i * vec.len() / new_len);
91 indices.map(|i| vec[i].clone()).collect()
92}
93
94pub fn resize_preserving_order_with_repeated_indices<T: Clone>(
102 vec: &[T],
103 new_len: usize,
104) -> (Vec<T>, Vec<usize>) {
105 let mut res = Vec::with_capacity(new_len);
106 let mut added_idxs = Vec::with_capacity(new_len);
107 let mut prev_index = None;
108 for i in 0..new_len {
109 let index = i * vec.len() / new_len;
110 if prev_index.map(|i| i == index).unwrap_or(false) {
111 added_idxs.push(res.len());
112 }
113 res.push(vec[index].clone());
114 prev_index = Some(index);
115 }
116 (res, added_idxs)
117}
118
119pub fn resize_preserving_order_with_repeated_cnt<T: Clone>(
127 vec: &[T],
128 new_len: usize,
129) -> (Vec<T>, Vec<usize>) {
130 let mut res = Vec::with_capacity(new_len);
131 let mut cnts = vec![0; vec.len()];
132
133 let mut src_indices = Vec::with_capacity(new_len);
134 for i in 0..new_len {
135 let index = i * vec.len() / new_len;
136 cnts[index] += 1;
137 res.push(vec[index].clone());
138 src_indices.push(index);
139 }
140 (res, src_indices.into_iter().map(|i| cnts[i]).collect())
141}
142
143pub fn extend_with_last<T: Clone + Default>(vec: &mut Vec<T>, new_len: usize) {
145 let v = vec![vec.last().cloned().unwrap_or_default(); new_len - vec.len()];
146 vec.extend(v)
147}
148
149fn merge_alpha(alpha: f32, n: usize) -> f32 {
151 let mut result = alpha;
152 for _ in 1..n {
153 result = result + (1.0 - result) * alpha;
154 }
155 result
156}
157
158pub fn apart_alpha(alpha: f32, n: usize, eps: f32) -> f32 {
160 if alpha == 0.0 {
161 return 0.0;
162 }
163 let mut left = (0.0, 0.0);
164 let mut right = (1.0, 1.0);
165
166 while right.0 - left.0 > eps {
167 let mid_single = (left.0 + right.0) / 2.0;
168 let mid_merged = merge_alpha(mid_single, n);
169
170 if (mid_merged - alpha).abs() < f32::EPSILON {
171 return mid_single;
172 }
173
174 if mid_merged < alpha {
175 left = (mid_single, mid_merged);
176 } else {
177 right = (mid_single, mid_merged);
178 }
179 }
180
181 ((left.0 + right.0) / 2.0).clamp(0.0, 1.0)
182}
183
184pub fn calculate_hash<T: Hash>(t: &T) -> u64 {
186 let mut s = DefaultHasher::new();
187 t.hash(&mut s);
188 s.finish()
189}
190
191pub fn wrap_point_func_with_point(
194 f: impl Fn(&mut DVec3) + Copy,
195 point: DVec3,
196) -> impl Fn(&mut DVec3) + Copy {
197 move |points| {
198 *points -= point;
199 f(points);
200 *points += point;
201 }
202}
203
204#[cfg(test)]
205mod test {
206 use super::*;
207
208 #[test]
209 fn test_resize_preserve_order_with_repeated_cnt() {
210 let values = vec![0, 1, 2, 3];
211 let (v, c) = resize_preserving_order_with_repeated_cnt(&values, 8);
212 assert_eq!(v, vec![0, 0, 1, 1, 2, 2, 3, 3]);
213 assert_eq!(c, vec![2; 8]);
214 }
215
216 #[test]
217 fn tset_apart_alpha() {
218 let a = apart_alpha(1.0, 10, 1e-3);
219 println!("{a}");
220 println!("{}", merge_alpha(1.0, 10));
221 }
222}