1use crate::data::graph::{Direction, EdgeIndex, Graph, NodeIndex};
2
3pub type ColliderGraphIndex = NodeIndex;
5pub type RigidBodyGraphIndex = NodeIndex;
7pub type TemporaryInteractionIndex = EdgeIndex;
9
10#[cfg_attr(feature = "serde-serialize", derive(Serialize, Deserialize))]
12#[derive(Clone, Debug)]
13pub struct InteractionGraph<N, E> {
14 pub(crate) graph: Graph<N, E>,
15}
16
17impl<N: Copy, E> Default for InteractionGraph<N, E> {
18 fn default() -> Self {
19 Self::new()
20 }
21}
22
23impl<N: Copy, E> InteractionGraph<N, E> {
24 pub fn new() -> Self {
26 InteractionGraph {
27 graph: Graph::with_capacity(10, 10),
28 }
29 }
30
31 pub fn raw_graph(&self) -> &Graph<N, E> {
33 &self.graph
34 }
35
36 pub(crate) fn invalid_graph_index() -> ColliderGraphIndex {
37 ColliderGraphIndex::new(crate::INVALID_U32)
38 }
39
40 pub(crate) fn is_graph_index_valid(index: ColliderGraphIndex) -> bool {
41 index.index() != crate::INVALID_USIZE
42 }
43
44 pub(crate) fn add_edge(
45 &mut self,
46 index1: ColliderGraphIndex,
47 index2: ColliderGraphIndex,
48 interaction: E,
49 ) -> TemporaryInteractionIndex {
50 self.graph.add_edge(index1, index2, interaction)
51 }
52
53 pub(crate) fn remove_edge(
54 &mut self,
55 index1: ColliderGraphIndex,
56 index2: ColliderGraphIndex,
57 ) -> Option<E> {
58 let id = self.graph.find_edge(index1, index2)?;
59 self.graph.remove_edge(id)
60 }
61
62 pub(crate) fn remove_edge_with(
65 &mut self,
66 index1: ColliderGraphIndex,
67 index2: ColliderGraphIndex,
68 on_remove: &mut dyn FnMut(TemporaryInteractionIndex),
69 ) -> Option<E> {
70 let id = self.graph.find_edge(index1, index2)?;
71 self.graph.remove_edge_with(id, on_remove)
72 }
73
74 #[must_use = "The graph index of the collision object returned by this method has been changed to `id`."]
81 pub(crate) fn remove_node(&mut self, id: ColliderGraphIndex) -> Option<N> {
82 let _ = self.graph.remove_node(id);
83 self.graph.node_weight(id).cloned()
84 }
85
86 pub(crate) fn remove_node_with(
89 &mut self,
90 id: ColliderGraphIndex,
91 on_remove: &mut dyn FnMut(TemporaryInteractionIndex),
92 ) -> Option<N> {
93 let _ = self.graph.remove_node_with(id, on_remove);
94 self.graph.node_weight(id).cloned()
95 }
96
97 pub fn interactions(&self) -> impl Iterator<Item = &E> {
99 self.graph.raw_edges().iter().map(move |edge| &edge.weight)
100 }
101
102 pub fn interactions_with_endpoints(&self) -> impl Iterator<Item = (N, N, &E)> {
104 self.graph.raw_edges().iter().map(move |edge| {
105 (
106 self.graph.raw_nodes()[edge.source().index()].weight,
107 self.graph.raw_nodes()[edge.target().index()].weight,
108 &edge.weight,
109 )
110 })
111 }
112
113 #[profiling::function]
115 pub fn interaction_pair(
116 &self,
117 id1: ColliderGraphIndex,
118 id2: ColliderGraphIndex,
119 ) -> Option<(N, N, &E)> {
120 self.graph.find_edge(id1, id2).and_then(|edge| {
121 let endpoints = self.graph.edge_endpoints(edge)?;
122 let h1 = self.graph.node_weight(endpoints.0)?;
123 let h2 = self.graph.node_weight(endpoints.1)?;
124 let weight = self.graph.edge_weight(edge)?;
125 Some((*h1, *h2, weight))
126 })
127 }
128
129 pub fn interactions_between(
134 &self,
135 id1: ColliderGraphIndex,
136 id2: ColliderGraphIndex,
137 ) -> impl Iterator<Item = (N, N, &E)> {
138 self.graph.edges_between(id1, id2).filter_map(move |edge| {
139 let endpoints = self.graph.edge_endpoints(edge)?;
140 let h1 = self.graph.node_weight(endpoints.0)?;
141 let h2 = self.graph.node_weight(endpoints.1)?;
142 let weight = self.graph.edge_weight(edge)?;
143 Some((*h1, *h2, weight))
144 })
145 }
146
147 #[profiling::function]
149 pub fn interaction_pair_mut(
150 &mut self,
151 id1: ColliderGraphIndex,
152 id2: ColliderGraphIndex,
153 ) -> Option<(N, N, &mut E)> {
154 let edge = self.graph.find_edge(id1, id2)?;
155 let endpoints = self.graph.edge_endpoints(edge)?;
156 let h1 = *self.graph.node_weight(endpoints.0)?;
157 let h2 = *self.graph.node_weight(endpoints.1)?;
158 let weight = self.graph.edge_weight_mut(edge)?;
159 Some((h1, h2, weight))
160 }
161
162 pub fn interactions_with(&self, id: ColliderGraphIndex) -> impl Iterator<Item = (N, N, &E)> {
164 self.graph.edges(id).map(move |e| {
165 let endpoints = self.graph.edge_endpoints(e.id()).unwrap();
166 (self.graph[endpoints.0], self.graph[endpoints.1], e.weight())
167 })
168 }
169
170 pub fn index_interaction(&self, id: TemporaryInteractionIndex) -> Option<(N, N, &E)> {
172 if let (Some(e), Some(endpoints)) =
173 (self.graph.edge_weight(id), self.graph.edge_endpoints(id))
174 {
175 Some((self.graph[endpoints.0], self.graph[endpoints.1], e))
176 } else {
177 None
178 }
179 }
180
181 pub fn interactions_with_mut(
183 &mut self,
184 id: ColliderGraphIndex,
185 ) -> impl Iterator<Item = (N, N, TemporaryInteractionIndex, &mut E)> {
186 let incoming_edge = self.graph.first_edge(id, Direction::Incoming);
187 let outgoing_edge = self.graph.first_edge(id, Direction::Outgoing);
188
189 InteractionsWithMut {
190 graph: &mut self.graph,
191 incoming_edge,
192 outgoing_edge,
193 }
194 }
195
196 }
253
254pub struct InteractionsWithMut<'a, N, E> {
255 graph: &'a mut Graph<N, E>,
256 incoming_edge: Option<EdgeIndex>,
257 outgoing_edge: Option<EdgeIndex>,
258}
259
260impl<'a, N: Copy, E> Iterator for InteractionsWithMut<'a, N, E> {
261 type Item = (N, N, TemporaryInteractionIndex, &'a mut E);
262
263 #[inline]
264 fn next(&mut self) -> Option<(N, N, TemporaryInteractionIndex, &'a mut E)> {
265 if let Some(edge) = self.incoming_edge {
266 self.incoming_edge = self.graph.next_edge(edge, Direction::Incoming);
267 let endpoints = self.graph.edge_endpoints(edge).unwrap();
268 let (co1, co2) = (self.graph[endpoints.0], self.graph[endpoints.1]);
269 let interaction = &mut self.graph[edge];
270 return Some((co1, co2, edge, unsafe {
271 core::mem::transmute::<&mut E, &'a mut E>(interaction)
272 }));
273 }
274
275 let edge = self.outgoing_edge?;
276 self.outgoing_edge = self.graph.next_edge(edge, Direction::Outgoing);
277 let endpoints = self.graph.edge_endpoints(edge).unwrap();
278 let (co1, co2) = (self.graph[endpoints.0], self.graph[endpoints.1]);
279 let interaction = &mut self.graph[edge];
280 Some((co1, co2, edge, unsafe {
281 core::mem::transmute::<&mut E, &'a mut E>(interaction)
282 }))
283 }
284}