rapier3d/dynamics/soft_body/tearing/
tearing_helpers.rs1use super::super::SoftBody;
3use crate::alloc_prelude::*;
4use crate::math::Real;
5#[cfg(not(feature = "std"))]
6#[allow(unused_imports)]
7use simba::scalar::{ComplexField as _, RealField as _};
8
9impl SoftBody {
10 pub fn connected_pieces(&self) -> Vec<Vec<u32>> {
14 let n = self.particles.len();
15 let mut parent: Vec<u32> = (0..n as u32).collect();
16 fn find(parent: &mut [u32], mut i: u32) -> u32 {
17 while parent[i as usize] != i {
18 let up = parent[parent[i as usize] as usize];
19 parent[i as usize] = up;
20 i = up;
21 }
22 i
23 }
24 let mut union = |vertices: &[u32]| {
25 for w in vertices.windows(2) {
26 let (a, b) = (find(&mut parent, w[0]), find(&mut parent, w[1]));
27 if a != b {
28 parent[a.max(b) as usize] = a.min(b);
29 }
30 }
31 };
32 for e in &self.edges {
33 union(&e.vertices);
34 }
35 for c in &self.cells {
36 union(&c.vertices);
37 }
38 #[cfg(feature = "dim3")]
39 for d in &self.dihedrals {
40 union(&d.vertices);
41 }
42 for s in &self.boundary {
43 union(s);
44 }
45 let mut piece_of_root = vec![u32::MAX; n];
47 let mut pieces: Vec<Vec<u32>> = Vec::new();
48 for v in 0..n as u32 {
49 let root = find(&mut parent, v) as usize;
50 if piece_of_root[root] == u32::MAX {
51 piece_of_root[root] = pieces.len() as u32;
52 pieces.push(Vec::new());
53 }
54 pieces[piece_of_root[root] as usize].push(v);
55 }
56 pieces
57 }
58
59 pub fn seeded_components(&self, members: Option<&[u32]>, seeds: &[[u32; 2]]) -> Vec<Vec<u32>> {
63 let n = self.particles.len();
64 let member =
65 |v: u32| (v as usize) < n && members.is_none_or(|m| m.binary_search(&v).is_ok());
66 let mut parent: Vec<u32> = (0..n as u32).collect();
67 fn find(parent: &mut [u32], mut i: u32) -> u32 {
68 while parent[i as usize] != i {
69 let up = parent[parent[i as usize] as usize];
70 parent[i as usize] = up;
71 i = up;
72 }
73 i
74 }
75 let mut union = |vertices: &[u32]| {
77 for i in 0..vertices.len() {
78 if !member(vertices[i]) {
79 continue;
80 }
81 for j in i + 1..vertices.len() {
82 if !member(vertices[j]) {
83 continue;
84 }
85 let (a, b) = (
86 find(&mut parent, vertices[i]),
87 find(&mut parent, vertices[j]),
88 );
89 if a != b {
90 parent[a.max(b) as usize] = a.min(b);
91 }
92 }
93 }
94 };
95 for e in &self.edges {
96 union(&e.vertices);
97 }
98 for c in &self.cells {
99 union(&c.vertices);
100 }
101 #[cfg(feature = "dim3")]
102 for d in &self.dihedrals {
103 union(&d.vertices);
104 }
105 for s in &self.boundary {
106 union(s);
107 }
108 let mut seeded = vec![false; n];
109 for pair in seeds {
110 for &v in pair {
111 if member(v) {
112 seeded[find(&mut parent, v) as usize] = true;
113 }
114 }
115 }
116 if seeded.iter().filter(|s| **s).count() < 2 {
117 return Vec::new();
118 }
119 let mut piece_of_root = vec![u32::MAX; n];
121 let mut pieces: Vec<Vec<u32>> = Vec::new();
122 let mut visit = |v: u32, parent: &mut [u32]| {
123 let root = find(parent, v) as usize;
124 if !seeded[root] {
125 return;
126 }
127 if piece_of_root[root] == u32::MAX {
128 piece_of_root[root] = pieces.len() as u32;
129 pieces.push(Vec::new());
130 }
131 pieces[piece_of_root[root] as usize].push(v);
132 };
133 match members {
134 Some(members) => members.iter().for_each(|&v| visit(v, &mut parent)),
135 None => (0..n as u32).for_each(|v| visit(v, &mut parent)),
136 }
137 pieces
138 }
139
140 pub fn mass_of(&self, particles: &[u32]) -> Real {
142 particles
143 .iter()
144 .filter_map(|&v| self.particles.get(v as usize))
145 .map(|p| p.mass)
146 .sum()
147 }
148
149 pub fn set_edge_tear_resistance(&mut self, i: usize, resistance: Real) {
152 if let Some(e) = self.edges.get_mut(i) {
153 e.tear_resistance = resistance.max(0.0);
154 self.modified = true;
155 }
156 }
157
158 pub fn set_cell_tear_resistance(&mut self, i: usize, resistance: Real) {
161 if let Some(c) = self.cells.get_mut(i) {
162 c.tear_resistance = resistance.max(0.0);
163 self.modified = true;
164 }
165 }
166
167 pub fn set_particle_damaged(&mut self, i: usize, damaged: bool) {
170 if let Some(p) = self.particles.get_mut(i) {
171 p.damaged = damaged;
172 self.modified = true;
173 }
174 }
175
176 pub(crate) fn effective_tear_resistance(&self, resistance: Real, vertices: &[u32]) -> Real {
180 let interior = self.material.interior_strength;
181 if interior > 1.0
182 && vertices.iter().all(|&v| {
183 let p = &self.particles[v as usize];
184 !p.on_surface && !p.damaged
185 })
186 {
187 resistance * interior
188 } else {
189 resistance
190 }
191 }
192}