chemrust_nasl/coordination_sites/
visualize.rs

1use std::f64::consts::FRAC_PI_2;
2
3use castep_periodic_table::element::ElementSymbol;
4use chemrust_core::data::geom::coordinates::CoordData;
5use nalgebra::{Matrix3, Point3, Vector3};
6
7use crate::DelegatePoint;
8
9use super::{CoordCircle, CoordSphere, MultiCoordPoint};
10
11pub trait Visualize {
12    type Output;
13    fn determine_coord(&self) -> Point3<f64>;
14    fn element_by_cn_number(&self) -> ElementSymbol;
15    fn draw_with_element(&self, element_symbol: ElementSymbol) -> Self::Output;
16    fn fractional_coord(&self, cell_tensor: Matrix3<f64>) -> Point3<f64> {
17        cell_tensor.try_inverse().expect("Matrix is not invertible") * self.determine_coord()
18    }
19}
20
21#[derive(Debug, Clone, Copy)]
22pub struct Atom {
23    symbol: ElementSymbol,
24    coord: CoordData,
25}
26
27impl Atom {
28    pub fn new(symbol: ElementSymbol, coord: CoordData) -> Self {
29        Self { symbol, coord }
30    }
31
32    pub fn coord(&self) -> CoordData {
33        self.coord
34    }
35
36    pub fn symbol(&self) -> ElementSymbol {
37        self.symbol
38    }
39}
40
41impl Visualize for CoordSphere {
42    type Output = Atom;
43
44    fn draw_with_element(&self, element_symbol: ElementSymbol) -> Self::Output {
45        let coord = CoordData::Cartesian(self.determine_coord());
46        Atom::new(element_symbol, coord)
47    }
48
49    fn determine_coord(&self) -> Point3<f64> {
50        let center = self.sphere.center();
51        let z_shift = Vector3::z_axis().scale(self.sphere.radius());
52        center + z_shift
53    }
54
55    fn element_by_cn_number(&self) -> ElementSymbol {
56        ElementSymbol::Xe
57    }
58}
59
60impl Visualize for CoordCircle {
61    type Output = Atom;
62
63    fn draw_with_element(&self, element_symbol: ElementSymbol) -> Self::Output {
64        Atom::new(element_symbol, CoordData::Cartesian(self.determine_coord()))
65    }
66
67    fn determine_coord(&self) -> Point3<f64> {
68        self.circle().get_point_on_circle(FRAC_PI_2)
69    }
70
71    fn element_by_cn_number(&self) -> ElementSymbol {
72        ElementSymbol::Ne
73    }
74}
75
76impl Visualize for MultiCoordPoint {
77    type Output = Atom;
78
79    fn draw_with_element(&self, element_symbol: ElementSymbol) -> Self::Output {
80        Atom::new(element_symbol, CoordData::Cartesian(self.determine_coord()))
81    }
82
83    fn determine_coord(&self) -> Point3<f64> {
84        self.point
85    }
86
87    fn element_by_cn_number(&self) -> ElementSymbol {
88        if self.atom_ids().len() < 104 {
89            ElementSymbol::try_from(self.atom_ids().len() as u8).unwrap_or(ElementSymbol::W)
90        } else {
91            ElementSymbol::Np
92        }
93    }
94}
95
96impl<const N: usize> Visualize for DelegatePoint<N> {
97    type Output = Atom;
98
99    fn determine_coord(&self) -> Point3<f64> {
100        self.point
101    }
102
103    fn element_by_cn_number(&self) -> ElementSymbol {
104        ElementSymbol::Xe
105    }
106
107    fn draw_with_element(&self, element_symbol: ElementSymbol) -> Self::Output {
108        Atom::new(element_symbol, CoordData::Cartesian(self.determine_coord()))
109    }
110}