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 #[must_use = "The graph index of the collision object returned by this method has been changed to `id`."]
77 pub(crate) fn remove_node(&mut self, id: ColliderGraphIndex) -> Option<N> {
78 let _ = self.graph.remove_node(id);
79 self.graph.node_weight(id).cloned()
80 }
81
82 pub fn interactions(&self) -> impl Iterator<Item = &E> {
84 self.graph.raw_edges().iter().map(move |edge| &edge.weight)
85 }
86
87 pub fn interactions_with_endpoints(&self) -> impl Iterator<Item = (N, N, &E)> {
89 self.graph.raw_edges().iter().map(move |edge| {
90 (
91 self.graph.raw_nodes()[edge.source().index()].weight,
92 self.graph.raw_nodes()[edge.target().index()].weight,
93 &edge.weight,
94 )
95 })
96 }
97
98 #[profiling::function]
100 pub fn interaction_pair(
101 &self,
102 id1: ColliderGraphIndex,
103 id2: ColliderGraphIndex,
104 ) -> Option<(N, N, &E)> {
105 self.graph.find_edge(id1, id2).and_then(|edge| {
106 let endpoints = self.graph.edge_endpoints(edge)?;
107 let h1 = self.graph.node_weight(endpoints.0)?;
108 let h2 = self.graph.node_weight(endpoints.1)?;
109 let weight = self.graph.edge_weight(edge)?;
110 Some((*h1, *h2, weight))
111 })
112 }
113
114 #[profiling::function]
116 pub fn interaction_pair_mut(
117 &mut self,
118 id1: ColliderGraphIndex,
119 id2: ColliderGraphIndex,
120 ) -> Option<(N, N, &mut E)> {
121 let edge = self.graph.find_edge(id1, id2)?;
122 let endpoints = self.graph.edge_endpoints(edge)?;
123 let h1 = *self.graph.node_weight(endpoints.0)?;
124 let h2 = *self.graph.node_weight(endpoints.1)?;
125 let weight = self.graph.edge_weight_mut(edge)?;
126 Some((h1, h2, weight))
127 }
128
129 pub fn interactions_with(&self, id: ColliderGraphIndex) -> impl Iterator<Item = (N, N, &E)> {
131 self.graph.edges(id).map(move |e| {
132 let endpoints = self.graph.edge_endpoints(e.id()).unwrap();
133 (self.graph[endpoints.0], self.graph[endpoints.1], e.weight())
134 })
135 }
136
137 pub fn index_interaction(&self, id: TemporaryInteractionIndex) -> Option<(N, N, &E)> {
139 if let (Some(e), Some(endpoints)) =
140 (self.graph.edge_weight(id), self.graph.edge_endpoints(id))
141 {
142 Some((self.graph[endpoints.0], self.graph[endpoints.1], e))
143 } else {
144 None
145 }
146 }
147
148 pub fn interactions_with_mut(
150 &mut self,
151 id: ColliderGraphIndex,
152 ) -> impl Iterator<Item = (N, N, TemporaryInteractionIndex, &mut E)> {
153 let incoming_edge = self.graph.first_edge(id, Direction::Incoming);
154 let outgoing_edge = self.graph.first_edge(id, Direction::Outgoing);
155
156 InteractionsWithMut {
157 graph: &mut self.graph,
158 incoming_edge,
159 outgoing_edge,
160 }
161 }
162
163 }
220
221pub struct InteractionsWithMut<'a, N, E> {
222 graph: &'a mut Graph<N, E>,
223 incoming_edge: Option<EdgeIndex>,
224 outgoing_edge: Option<EdgeIndex>,
225}
226
227impl<'a, N: Copy, E> Iterator for InteractionsWithMut<'a, N, E> {
228 type Item = (N, N, TemporaryInteractionIndex, &'a mut E);
229
230 #[inline]
231 fn next(&mut self) -> Option<(N, N, TemporaryInteractionIndex, &'a mut E)> {
232 if let Some(edge) = self.incoming_edge {
233 self.incoming_edge = self.graph.next_edge(edge, Direction::Incoming);
234 let endpoints = self.graph.edge_endpoints(edge).unwrap();
235 let (co1, co2) = (self.graph[endpoints.0], self.graph[endpoints.1]);
236 let interaction = &mut self.graph[edge];
237 return Some((co1, co2, edge, unsafe {
238 std::mem::transmute::<&mut E, &'a mut E>(interaction)
239 }));
240 }
241
242 let edge = self.outgoing_edge?;
243 self.outgoing_edge = self.graph.next_edge(edge, Direction::Outgoing);
244 let endpoints = self.graph.edge_endpoints(edge).unwrap();
245 let (co1, co2) = (self.graph[endpoints.0], self.graph[endpoints.1]);
246 let interaction = &mut self.graph[edge];
247 Some((co1, co2, edge, unsafe {
248 std::mem::transmute::<&mut E, &'a mut E>(interaction)
249 }))
250 }
251}