ak_vis/viewer/session/
selection.rs1use ak_core::Trajectory;
2
3#[derive(Clone, Debug, PartialEq, Eq)]
4pub struct SelectionFrames {
5 pub(super) frames: Vec<Vec<bool>>,
6 pub(super) ordered: Vec<Vec<usize>>,
7}
8
9#[derive(Clone, Copy, Debug, PartialEq, Eq, Hash)]
10pub struct SelectedImageAtom {
11 pub atom_index: usize,
12 pub image_offset: [i32; 3],
13}
14
15#[derive(Clone, Debug, PartialEq, Eq)]
16pub struct ImageSelectionFrames {
17 pub(super) frames: Vec<Vec<SelectedImageAtom>>,
18}
19
20impl SelectionFrames {
21 pub fn new(traj: &Trajectory) -> Self {
22 Self {
23 frames: (0..traj.len())
24 .map(|index| vec![false; traj.view(index).positions.len()])
25 .collect(),
26 ordered: vec![Vec::new(); traj.len()],
27 }
28 }
29
30 pub fn get(&self, frame_index: usize) -> Option<&[bool]> {
31 self.frames.get(frame_index).map(Vec::as_slice)
32 }
33
34 pub fn replace(&mut self, frame_index: usize, selection: Vec<bool>) {
35 if frame_index < self.frames.len() && self.frames[frame_index].len() == selection.len() {
36 self.frames[frame_index] = selection;
37 self.ordered[frame_index] = self.frames[frame_index]
38 .iter()
39 .enumerate()
40 .filter_map(|(index, selected)| selected.then_some(index))
41 .collect();
42 }
43 }
44
45 pub fn add(&mut self, frame_index: usize, selection: &[bool]) {
46 if let Some(current) = self.frames.get_mut(frame_index) {
47 if current.len() != selection.len() {
48 return;
49 }
50 for (slot, selected) in current.iter_mut().zip(selection.iter().copied()) {
51 *slot |= selected;
52 }
53 let ordered = &mut self.ordered[frame_index];
54 for (index, selected) in selection.iter().copied().enumerate() {
55 if selected && current[index] && !ordered.contains(&index) {
56 ordered.push(index);
57 }
58 }
59 }
60 }
61
62 pub fn remove(&mut self, frame_index: usize, selection: &[bool]) {
63 if let Some(current) = self.frames.get_mut(frame_index) {
64 if current.len() != selection.len() {
65 return;
66 }
67 for (slot, selected) in current.iter_mut().zip(selection.iter().copied()) {
68 if selected {
69 *slot = false;
70 }
71 }
72 self.ordered[frame_index].retain(|index| current.get(*index).copied().unwrap_or(false));
73 }
74 }
75
76 pub fn clear(&mut self, frame_index: usize) {
77 if let Some(current) = self.frames.get_mut(frame_index) {
78 current.fill(false);
79 self.ordered[frame_index].clear();
80 }
81 }
82
83 pub fn append_empty_for_atom_count(&mut self, atom_count: usize) {
84 self.frames.push(vec![false; atom_count]);
85 self.ordered.push(Vec::new());
86 }
87
88 pub fn selected_main_images(&self, frame_index: usize) -> Vec<SelectedImageAtom> {
89 self.selected_indices(frame_index)
90 .into_iter()
91 .map(|atom_index| SelectedImageAtom {
92 atom_index,
93 image_offset: [0, 0, 0],
94 })
95 .collect()
96 }
97
98 pub fn selected_indices(&self, frame_index: usize) -> Vec<usize> {
99 self.ordered.get(frame_index).cloned().unwrap_or_default()
100 }
101
102 pub(crate) fn set_order(&mut self, frame_index: usize, ordered: Vec<usize>) {
103 if frame_index < self.ordered.len() {
104 self.ordered[frame_index] = ordered;
105 }
106 }
107
108 pub(crate) fn mask_from_images(atom_count: usize, atoms: &[SelectedImageAtom]) -> Vec<bool> {
109 let mut mask = vec![false; atom_count];
110 for atom in atoms {
111 if atom.atom_index < atom_count {
112 mask[atom.atom_index] = true;
113 }
114 }
115 mask
116 }
117
118 pub(crate) fn ordered_atoms_from_images(atoms: &[SelectedImageAtom]) -> Vec<usize> {
119 let mut ordered = Vec::new();
120 for atom in atoms {
121 if !ordered.contains(&atom.atom_index) {
122 ordered.push(atom.atom_index);
123 }
124 }
125 ordered
126 }
127}
128
129impl ImageSelectionFrames {
130 pub fn new(frame_count: usize) -> Self {
131 Self {
132 frames: vec![Vec::new(); frame_count],
133 }
134 }
135
136 pub fn get(&self, frame_index: usize) -> Option<&[SelectedImageAtom]> {
137 self.frames.get(frame_index).map(Vec::as_slice)
138 }
139
140 pub fn selected(&self, frame_index: usize) -> Vec<SelectedImageAtom> {
141 self.frames.get(frame_index).cloned().unwrap_or_default()
142 }
143
144 pub fn replace(&mut self, frame_index: usize, selection: Vec<SelectedImageAtom>) {
145 if frame_index < self.frames.len() {
146 self.frames[frame_index] = dedup_image_selection(selection);
147 }
148 }
149
150 pub fn add(&mut self, frame_index: usize, selection: &[SelectedImageAtom]) {
151 let Some(current) = self.frames.get_mut(frame_index) else {
152 return;
153 };
154 for atom in selection.iter().copied() {
155 if !current.contains(&atom) {
156 current.push(atom);
157 }
158 }
159 }
160
161 pub fn remove(&mut self, frame_index: usize, selection: &[SelectedImageAtom]) {
162 let Some(current) = self.frames.get_mut(frame_index) else {
163 return;
164 };
165 current.retain(|atom| !selection.contains(atom));
166 }
167
168 pub fn clear(&mut self, frame_index: usize) {
169 if frame_index < self.frames.len() {
170 self.frames[frame_index].clear();
171 }
172 }
173
174 pub fn append_empty_frame(&mut self) {
175 self.frames.push(Vec::new());
176 }
177
178 pub(super) fn replace_single(&mut self, frame_index: usize, atom: SelectedImageAtom) -> bool {
179 let Some(current) = self.frames.get_mut(frame_index) else {
180 return false;
181 };
182 if current.as_slice() == [atom] {
183 return false;
184 }
185 current.clear();
186 current.push(atom);
187 true
188 }
189
190 pub(super) fn toggle(&mut self, frame_index: usize, atom: SelectedImageAtom) -> bool {
191 let Some(current) = self.frames.get_mut(frame_index) else {
192 return false;
193 };
194 if let Some(index) = current.iter().position(|selected| *selected == atom) {
195 current.remove(index);
196 } else {
197 current.push(atom);
198 }
199 true
200 }
201}
202
203fn dedup_image_selection(selection: Vec<SelectedImageAtom>) -> Vec<SelectedImageAtom> {
204 let mut deduped = Vec::new();
205 for atom in selection {
206 if !deduped.contains(&atom) {
207 deduped.push(atom);
208 }
209 }
210 deduped
211}