1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
use std::{
collections::HashMap,
hash::{Hash, Hasher},
};
use crate::*;
pub fn to_words_skip_empty(line: &[u8]) -> impl Iterator<Item = &[u8]> {
line.split(|x| *x == b' ' || *x == b'\t').skip_empty()
}
pub fn until<'a>(line: &'a str, delimiter: &str) -> &'a str {
line.split(delimiter).next().unwrap_or("")
}
pub fn until_bytes<'a>(line: &'a [u8], delimiter: u8) -> &'a [u8] {
line.split(|x| *x == delimiter).next().unwrap_or(&[])
}
pub fn max_f64(a: f64, b: f64) -> f64 {
if a > b {
return a;
}
b
}
pub fn contains<T>(haystack: &[T], needle: &[T]) -> bool
where
T: PartialEq,
{
haystack.windows(needle.len()).any(|x| x == needle)
}
pub fn max_f64_3(a: f64, b: f64, c: f64) -> f64 {
max_f64(max_f64(a, b), c)
}
#[inline(always)]
pub fn hash_f64<H>(x: f64, state: &mut H)
where
H: Hasher,
{
x.to_bits().hash(state);
}
pub fn pack_dupes_indexed<'a, I, T>(idata: I) -> (Vec<T>, Vec<usize>)
where
I: Iterator<Item = &'a T>,
T: 'a + Eq + Hash + Clone,
{
let mut map = HashMap::new();
let mut packed_data = Vec::new();
let mut ids = Vec::new();
for x in idata {
let id = map.entry(x).or_insert_with(|| {
let value = packed_data.len();
packed_data.push(x.clone());
value
});
ids.push(*id);
}
(packed_data, ids)
}
pub fn normals_of_mesh<P, M>(mesh: &M) -> Vec<Norm3D>
where
M: IsMesh<P, Face3>,
P: IsBuildable3D + Default + Clone,
{
let n = mesh.num_vertices();
let nf = mesh.num_faces();
let mut ns = vec![P::default(); n];
for i in 0..nf {
let face = mesh.face_vertex_ids(FId { val: i }).unwrap();
let [v1, v2, v3] = mesh.face_vertices(FId { val: i }).unwrap();
let v12 = conn(&v1, &v2);
let v13 = conn(&v1, &v3);
let n = Norm3D::new(cross(&v12, &v13)).unwrap_or(Norm3D::norm_z());
for j in 0..3 {
let new = add(&ns[face.vid(j).unwrap().val], &n);
ns[face.vid(j).unwrap().val] = new;
}
}
ns.into_iter()
.map(|x| Norm3D::new(x).unwrap_or(Norm3D::norm_z()))
.collect()
}
pub fn estimate_delimiter(minimum_count: usize, line: &[u8]) -> Option<u8> {
for candidate in [b' ', b';', b',', b'\t'].iter() {
if line.iter().filter(|c| **c == *candidate).count() >= minimum_count {
return Some(*candidate);
}
}
None
}
pub fn add<P, Q>(p: &P, q: &Q) -> P
where
P: IsBuildable3D,
Q: Is3D,
{
P::new(p.x() + q.x(), p.y() + q.y(), p.z() + q.z())
}