use std::collections::{BTreeMap, BTreeSet};
use serde::{Deserialize, Serialize};
#[derive(Debug, Clone, Default, PartialEq, Eq, Serialize, Deserialize)]
pub struct Selection {
pub atoms: BTreeSet<usize>,
pub bonds: BTreeSet<(usize, usize)>,
}
impl Selection {
#[must_use]
pub fn new() -> Self {
Self::default()
}
pub fn add_atom(&mut self, index: usize) {
self.atoms.insert(index);
}
pub fn remove_atom(&mut self, index: usize) {
self.atoms.remove(&index);
}
pub fn toggle_atom(&mut self, index: usize) {
if !self.atoms.insert(index) {
self.atoms.remove(&index);
}
}
pub fn add_atoms(&mut self, indices: impl IntoIterator<Item = usize>) {
self.atoms.extend(indices);
}
pub fn add_bond(&mut self, first: usize, second: usize) {
self.bonds.insert((first.min(second), first.max(second)));
}
#[must_use]
pub fn contains(&self, index: usize) -> bool {
self.atoms.contains(&index)
}
#[must_use]
pub fn len(&self) -> usize {
self.atoms.len()
}
#[must_use]
pub fn is_empty(&self) -> bool {
self.atoms.is_empty() && self.bonds.is_empty()
}
pub fn clear(&mut self) {
self.atoms.clear();
self.bonds.clear();
}
pub fn union(&mut self, other: &Self) {
self.atoms.extend(other.atoms.iter().copied());
self.bonds.extend(other.bonds.iter().copied());
}
pub fn intersect(&mut self, other: &Self) {
self.atoms.retain(|index| other.atoms.contains(index));
self.bonds.retain(|bond| other.bonds.contains(bond));
}
}
#[derive(Debug, Clone, Copy, PartialEq, Eq, PartialOrd, Ord, Hash, Serialize, Deserialize)]
pub struct AtomId(pub u64);
#[derive(Debug, Clone, Default, PartialEq, Eq, Serialize, Deserialize)]
pub struct TrackingTable {
pub by_id: BTreeMap<AtomId, usize>,
next: u64,
}
impl TrackingTable {
#[must_use]
pub fn new() -> Self {
Self::default()
}
pub fn assign(&mut self, site: usize) -> AtomId {
let id = AtomId(self.next);
self.next += 1;
self.by_id.insert(id, site);
id
}
#[must_use]
pub fn site_of(&self, id: AtomId) -> Option<usize> {
self.by_id.get(&id).copied()
}
#[must_use]
pub fn id_of(&self, site: usize) -> Option<AtomId> {
self.by_id
.iter()
.find(|(_, index)| **index == site)
.map(|(id, _)| *id)
}
pub fn remove(&mut self, id: AtomId) {
self.by_id.remove(&id);
}
pub fn remap(&mut self, mapping: &BTreeMap<usize, usize>) {
self.by_id.retain(|_, site| {
if let Some(new) = mapping.get(site) {
*site = *new;
true
} else {
false
}
});
}
}