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`."]
69 pub(crate) fn remove_node(&mut self, id: ColliderGraphIndex) -> Option<N> {
70 let _ = self.graph.remove_node(id);
71 self.graph.node_weight(id).cloned()
72 }
73
74 pub fn interactions(&self) -> impl Iterator<Item = &E> {
76 self.graph.raw_edges().iter().map(move |edge| &edge.weight)
77 }
78
79 pub fn interactions_with_endpoints(&self) -> impl Iterator<Item = (N, N, &E)> {
81 self.graph.raw_edges().iter().map(move |edge| {
82 (
83 self.graph.raw_nodes()[edge.source().index()].weight,
84 self.graph.raw_nodes()[edge.target().index()].weight,
85 &edge.weight,
86 )
87 })
88 }
89
90 #[profiling::function]
92 pub fn interaction_pair(
93 &self,
94 id1: ColliderGraphIndex,
95 id2: ColliderGraphIndex,
96 ) -> Option<(N, N, &E)> {
97 self.graph.find_edge(id1, id2).and_then(|edge| {
98 let endpoints = self.graph.edge_endpoints(edge)?;
99 let h1 = self.graph.node_weight(endpoints.0)?;
100 let h2 = self.graph.node_weight(endpoints.1)?;
101 let weight = self.graph.edge_weight(edge)?;
102 Some((*h1, *h2, weight))
103 })
104 }
105
106 #[profiling::function]
108 pub fn interaction_pair_mut(
109 &mut self,
110 id1: ColliderGraphIndex,
111 id2: ColliderGraphIndex,
112 ) -> Option<(N, N, &mut E)> {
113 let edge = self.graph.find_edge(id1, id2)?;
114 let endpoints = self.graph.edge_endpoints(edge)?;
115 let h1 = *self.graph.node_weight(endpoints.0)?;
116 let h2 = *self.graph.node_weight(endpoints.1)?;
117 let weight = self.graph.edge_weight_mut(edge)?;
118 Some((h1, h2, weight))
119 }
120
121 pub fn interactions_with(&self, id: ColliderGraphIndex) -> impl Iterator<Item = (N, N, &E)> {
123 self.graph.edges(id).map(move |e| {
124 let endpoints = self.graph.edge_endpoints(e.id()).unwrap();
125 (self.graph[endpoints.0], self.graph[endpoints.1], e.weight())
126 })
127 }
128
129 pub fn index_interaction(&self, id: TemporaryInteractionIndex) -> Option<(N, N, &E)> {
131 if let (Some(e), Some(endpoints)) =
132 (self.graph.edge_weight(id), self.graph.edge_endpoints(id))
133 {
134 Some((self.graph[endpoints.0], self.graph[endpoints.1], e))
135 } else {
136 None
137 }
138 }
139
140 pub fn interactions_with_mut(
142 &mut self,
143 id: ColliderGraphIndex,
144 ) -> impl Iterator<Item = (N, N, TemporaryInteractionIndex, &mut E)> {
145 let incoming_edge = self.graph.first_edge(id, Direction::Incoming);
146 let outgoing_edge = self.graph.first_edge(id, Direction::Outgoing);
147
148 InteractionsWithMut {
149 graph: &mut self.graph,
150 incoming_edge,
151 outgoing_edge,
152 }
153 }
154
155 }
212
213pub struct InteractionsWithMut<'a, N, E> {
214 graph: &'a mut Graph<N, E>,
215 incoming_edge: Option<EdgeIndex>,
216 outgoing_edge: Option<EdgeIndex>,
217}
218
219impl<'a, N: Copy, E> Iterator for InteractionsWithMut<'a, N, E> {
220 type Item = (N, N, TemporaryInteractionIndex, &'a mut E);
221
222 #[inline]
223 fn next(&mut self) -> Option<(N, N, TemporaryInteractionIndex, &'a mut E)> {
224 if let Some(edge) = self.incoming_edge {
225 self.incoming_edge = self.graph.next_edge(edge, Direction::Incoming);
226 let endpoints = self.graph.edge_endpoints(edge).unwrap();
227 let (co1, co2) = (self.graph[endpoints.0], self.graph[endpoints.1]);
228 let interaction = &mut self.graph[edge];
229 return Some((co1, co2, edge, unsafe {
230 std::mem::transmute::<&mut E, &'a mut E>(interaction)
231 }));
232 }
233
234 let edge = self.outgoing_edge?;
235 self.outgoing_edge = self.graph.next_edge(edge, Direction::Outgoing);
236 let endpoints = self.graph.edge_endpoints(edge).unwrap();
237 let (co1, co2) = (self.graph[endpoints.0], self.graph[endpoints.1]);
238 let interaction = &mut self.graph[edge];
239 Some((co1, co2, edge, unsafe {
240 std::mem::transmute::<&mut E, &'a mut E>(interaction)
241 }))
242 }
243}