use crate::{traits::*, GraphErrors, GenericGraph};
#[cfg(feature = "serde_support")]
use serde::{Serialize, Deserialize};
#[derive(Debug, Clone)]
#[cfg_attr(feature = "serde_support", derive(Serialize, Deserialize))]
pub struct SpacialNodeContainer<T>
{
pub(crate) adj: Vec<usize>,
id: usize,
pub(crate) x: f64,
pub(crate) y: f64,
node: T,
}
impl<T: Node + SerdeStateConform> AdjContainer<T> for SpacialNodeContainer<T> {
fn new(id: usize, node: T) -> Self {
SpacialNodeContainer{
id,
adj: Vec::new(),
node,
x: f64::NAN,
y: f64::NAN,
}
}
fn contained(&self) -> &T {
&self.node
}
fn contained_mut(&mut self) -> &mut T {
&mut self.node
}
fn neighbors(&self) -> IterWrapper {
IterWrapper::new_generic(self.adj.iter())
}
fn degree(&self) -> usize {
self.adj.len()
}
fn id(&self) -> usize {
self.id
}
fn is_adjacent(&self, other_id: usize) -> bool {
self.adj.contains(&other_id)
}
fn sort_adj(&mut self) {
self.adj.sort_unstable();
}
#[doc(hidden)]
unsafe fn clear_edges(&mut self) {
self.adj.clear();
}
#[doc(hidden)]
unsafe fn push(&mut self, other: &mut Self)
-> Result<(), GraphErrors>
{
if self.is_adjacent(other.id()) {
return Err(GraphErrors::EdgeExists);
}
self.adj.push(other.id());
other.adj.push(self.id);
Ok(())
}
#[doc(hidden)]
unsafe fn remove(&mut self, other: &mut Self)
-> Result<(), GraphErrors>
{
if !self.is_adjacent(other.id()){
return Err(GraphErrors::EdgeDoesNotExist);
}
self.swap_remove_element(other.id());
other.swap_remove_element(self.id());
Ok(())
}
fn get_adj_first(&self) -> Option<&usize> {
self.adj.first()
}
}
impl<T> SpacialNodeContainer<T> {
fn swap_remove_element(&mut self, elem: usize) {
let index = self.adj
.iter()
.position(|&x| x == elem)
.expect("swap_remove_element ERROR 0");
self.adj
.swap_remove(index);
}
pub fn distance(&self, other: &Self) -> f64 {
let x = self.x - other.x;
let y = self.y - other.y;
y.hypot(x)
}
}
pub type SpacialGraph<T> = GenericGraph<T, SpacialNodeContainer<T>>;
impl<T> SpacialGraph<T>
{
pub fn distance(&self, i: usize, j: usize) -> Option<f64>
where SpacialNodeContainer<T>: AdjContainer<T>
{
let container_i = self.container_checked(i)?;
self.container_checked(j)
.map(
|container_j|
{
container_i.distance(container_j)
}
)
}
}