use chematic_core::AtomIdx;
#[derive(Debug, Clone, Copy, PartialEq)]
pub struct Point3 {
pub x: f64,
pub y: f64,
pub z: f64,
}
impl Point3 {
#[inline]
pub fn new(x: f64, y: f64, z: f64) -> Self {
Self { x, y, z }
}
#[inline]
pub fn zero() -> Self {
Self::new(0.0, 0.0, 0.0)
}
#[inline]
pub fn distance(&self, other: &Self) -> f64 {
let dx = self.x - other.x;
let dy = self.y - other.y;
let dz = self.z - other.z;
(dx * dx + dy * dy + dz * dz).sqrt()
}
#[inline]
pub fn add(&self, other: &Self) -> Self {
Self::new(self.x + other.x, self.y + other.y, self.z + other.z)
}
#[inline]
pub fn sub(&self, other: &Self) -> Self {
Self::new(self.x - other.x, self.y - other.y, self.z - other.z)
}
#[inline]
pub fn scale(&self, s: f64) -> Self {
Self::new(self.x * s, self.y * s, self.z * s)
}
#[inline]
pub fn dot(&self, other: &Self) -> f64 {
self.x * other.x + self.y * other.y + self.z * other.z
}
#[inline]
pub fn cross(&self, other: &Self) -> Self {
Self::new(
self.y * other.z - self.z * other.y,
self.z * other.x - self.x * other.z,
self.x * other.y - self.y * other.x,
)
}
#[inline]
pub fn norm(&self) -> f64 {
(self.x * self.x + self.y * self.y + self.z * self.z).sqrt()
}
pub fn normalize(&self) -> Self {
let n = self.norm();
assert!(n > 0.0, "cannot normalize a zero-length vector");
self.scale(1.0 / n)
}
}
#[derive(Debug, Clone)]
pub struct Coords3D {
pub points: Vec<Point3>,
}
impl Coords3D {
pub fn new_zeroed(n: usize) -> Self {
Self {
points: vec![Point3::zero(); n],
}
}
pub fn get(&self, idx: AtomIdx) -> Point3 {
self.points[idx.0 as usize]
}
pub fn set(&mut self, idx: AtomIdx, p: Point3) {
self.points[idx.0 as usize] = p;
}
pub fn atom_count(&self) -> usize {
self.points.len()
}
}