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
use crate::{functions::conn, prelude::*};
use fnv::FnvHashMap;
use std::hash::Hash;
pub fn cluster_vertices<P, M>(mesh: &M, cluster_size: f64) -> Result<M>
where
M: IsFaceEditableMesh<P, Face3>
+ IsVertexEditableMesh<P, Face3>
+ Default
+ HasBoundingBox3DMaybe,
P: IsBuildable3D + Eq + Hash + Clone,
{
let bb = mesh.bounding_box_maybe()?;
let (sx, sy, sz) = bb.sizes();
let min = P::new_from(&bb.min_p());
let (nx, ny, nz) = (
(sx.get() / cluster_size) as usize,
(sy.get() / cluster_size) as usize,
(sz.get() / cluster_size) as usize,
);
if nx < 2 || ny < 2 || nz < 2 {
return Err(ErrorKind::ClusterTooBig);
}
let cluster_of = |ref p| {
let v = conn(&min, p);
(
(v.x() / cluster_size) as usize,
(v.y() / cluster_size) as usize,
(v.z() / cluster_size) as usize,
)
};
let nv = mesh.num_vertices();
let mut cluster_map = FnvHashMap::default();
let mut clusters = Vec::with_capacity(nv);
for i in 0..nv {
let p = mesh.vertex(VId { val: i }).unwrap();
let cluster = cluster_of(p);
cluster_map.insert(cluster, i);
clusters.push(cluster);
}
let mut result = M::default();
let new_vertex = |old_index| {
let cluster = &clusters[old_index];
mesh.vertex(VId {
val: *cluster_map.get(cluster).unwrap(),
})
.unwrap()
};
let nf = mesh.num_faces();
for i in 0..nf {
let f = mesh.face_vertex_ids(FId { val: i }).unwrap();
result.add_face(
new_vertex(f.a.val),
new_vertex(f.b.val),
new_vertex(f.c.val),
);
}
result = heal_mesh(&result)?;
Ok(result)
}