#[cxx::bridge(namespace = "voro")]
pub mod ffi {
unsafe extern "C++" {
include!("voro_rs/src/boilerplate.hh");
type voronoicell = crate::cell::ffi::voronoicell;
type voronoicell_neighbor =
crate::cell::ffi::voronoicell_neighbor;
type wall = crate::wall::ffi::wall;
type wall_list;
#[rust_name = "new_wall_list"]
fn construct() -> UniquePtr<wall_list>;
unsafe fn add_wall(
self: Pin<&mut wall_list>,
w: Pin<&mut wall>,
);
#[rust_name = "add_walls"]
unsafe fn add_wall(
self: Pin<&mut wall_list>,
w: Pin<&mut wall_list>,
);
fn point_inside_walls(
self: Pin<&mut wall_list>,
x: f64,
y: f64,
z: f64,
) -> bool;
#[rust_name = "apply_walls_0"]
fn apply_walls(
self: Pin<&mut wall_list>,
c: Pin<&mut voronoicell>,
x: f64,
y: f64,
z: f64,
) -> bool;
#[rust_name = "apply_walls_1"]
fn apply_walls(
self: Pin<&mut wall_list>,
c: Pin<&mut voronoicell_neighbor>,
x: f64,
y: f64,
z: f64,
) -> bool;
}
}
use crate::cell::{VoroCell, VoroCellNbr, VoroCellSgl};
use crate::container::ffi::{
container_poly_to_wall_list, container_to_wall_list,
};
use crate::container::{ContainerRad, ContainerStd};
use crate::wall::ffi::{
wall_cone_to_wall, wall_cylinder_to_wall,
wall_plane_to_wall, wall_sphere_to_wall,
};
use crate::wall::{
Wall, WallCone, WallCylinder, WallPlane, WallSphere,
};
use cxx::UniquePtr;
use std::marker::PhantomData;
type DVec3 = [f64; 3];
pub struct WallList<'a> {
pub(crate) inner: UniquePtr<ffi::wall_list>,
phantom: PhantomData<&'a ()>,
}
impl<'a> WallList<'a> {
pub fn new() -> Self {
Self {
inner: ffi::new_wall_list(),
phantom: PhantomData,
}
}
}
pub trait Walls0 {
fn point_inside_walls(&mut self, xyz: DVec3) -> bool;
}
impl<'a> Walls0 for WallList<'a> {
fn point_inside_walls(&mut self, xyz: DVec3) -> bool {
self.inner
.pin_mut()
.point_inside_walls(xyz[0], xyz[1], xyz[2])
}
}
pub trait Walls1<T: VoroCell> {
fn apply_walls(
&mut self,
cell: &mut T,
xyz: DVec3,
) -> bool;
}
impl<'a> Walls1<VoroCellSgl> for WallList<'a> {
fn apply_walls(
&mut self,
cell: &mut VoroCellSgl,
xyz: DVec3,
) -> bool {
self.inner.pin_mut().apply_walls_0(
cell.inner.pin_mut(),
xyz[0],
xyz[1],
xyz[2],
)
}
}
impl<'a> Walls1<VoroCellNbr> for WallList<'a> {
fn apply_walls(
&mut self,
cell: &mut VoroCellNbr,
xyz: DVec3,
) -> bool {
self.inner.pin_mut().apply_walls_1(
cell.inner.pin_mut(),
xyz[0],
xyz[1],
xyz[2],
)
}
}
pub trait Walls2<'a, T: Wall> {
fn add_wall(&mut self, wall: &'a mut T);
}
impl<'a> Walls2<'a, WallSphere> for WallList<'a> {
fn add_wall(&mut self, wall: &'a mut WallSphere) {
let w0 = wall_sphere_to_wall(wall.inner.pin_mut());
unsafe {
self.inner.pin_mut().add_wall(w0);
}
}
}
impl<'a> Walls2<'a, WallPlane> for WallList<'a> {
fn add_wall(&mut self, wall: &'a mut WallPlane) {
let w0 = wall_plane_to_wall(wall.inner.pin_mut());
unsafe {
self.inner.pin_mut().add_wall(w0);
}
}
}
impl<'a> Walls2<'a, WallCylinder> for WallList<'a> {
fn add_wall(&mut self, wall: &'a mut WallCylinder) {
let w0 =
wall_cylinder_to_wall(wall.inner.pin_mut());
unsafe {
self.inner.pin_mut().add_wall(w0);
}
}
}
impl<'a> Walls2<'a, WallCone> for WallList<'a> {
fn add_wall(&mut self, wall: &'a mut WallCone) {
let w0 = wall_cone_to_wall(wall.inner.pin_mut());
unsafe {
self.inner.pin_mut().add_wall(w0);
}
}
}
pub trait Walls3<'a, T: Walls<'a>> {
fn add_walls(&mut self, walls: &mut T);
}
impl<'a> Walls3<'a, WallList<'a>> for WallList<'a> {
fn add_walls(&mut self, walls: &mut WallList<'a>) {
unsafe {
self.inner
.pin_mut()
.add_walls(walls.inner.pin_mut())
}
}
}
impl<'a> Walls3<'a, ContainerStd<'a>> for WallList<'a> {
fn add_walls(&mut self, walls: &mut ContainerStd<'a>) {
unsafe {
self.inner.pin_mut().add_walls(
container_to_wall_list(
walls.inner.pin_mut(),
),
)
}
}
}
impl<'a> Walls3<'a, ContainerRad<'a>> for WallList<'a> {
fn add_walls(&mut self, walls: &mut ContainerRad<'a>) {
unsafe {
self.inner.pin_mut().add_walls(
container_poly_to_wall_list(
walls.inner.pin_mut(),
),
)
}
}
}
pub trait Walls<'a>:
Walls0
+ Walls1<VoroCellSgl>
+ Walls1<VoroCellNbr>
+ Walls2<'a, WallSphere>
+ Walls2<'a, WallPlane>
+ Walls2<'a, WallCylinder>
+ Walls2<'a, WallCone>
+ Walls3<'a, WallList<'a>>
+ Walls3<'a, ContainerStd<'a>>
+ Walls3<'a, ContainerRad<'a>>
{
}
impl<'a> Walls<'a> for WallList<'a> {}
#[cfg(test)]
mod tests {
use super::*;
use crate::{
cell::{VoroCell, VoroCellSgl},
wall::{Wall1, WallSphere},
};
#[test]
fn basic_test() {
let mut c0 = VoroCellSgl::new(
[-1.0, -1.0, -1.0],
[1.0, 1.0, 1.0],
);
let mut c1 = c0.clone();
let mut c2 = c0.clone();
let mut c3 = c0.clone();
assert_eq!(c0.volume(), 8.0);
assert_eq!(c1.volume(), 8.0);
assert_eq!(c2.volume(), 8.0);
assert_eq!(c3.volume(), 8.0);
let mut w0 =
WallSphere::new([0.0, 0.0, 100.0], 100.0);
let mut w1 =
WallSphere::new([0.0, 100.0, 0.0], 100.0);
w0.cut_cell(&mut c0, [0.0, 0.0, 0.0]);
assert_eq!(c0.volume(), 4.0);
w1.cut_cell(&mut c0, [0.0, 0.0, 0.0]);
assert_eq!(c0.volume(), 2.0);
let mut wl = WallList::new();
wl.add_wall(&mut w0);
wl.apply_walls(&mut c1, [0.0, 0.0, 0.0]);
assert_eq!(c1.volume(), 4.0);
wl.add_wall(&mut w1);
wl.apply_walls(&mut c1, [0.0, 0.0, 0.0]);
wl.apply_walls(&mut c2, [0.0, 0.0, 0.0]);
assert_eq!(c1.volume(), 2.0);
assert_eq!(c2.volume(), 2.0);
let mut wl2 = WallList::new();
wl2.add_walls(&mut wl);
wl2.apply_walls(&mut c3, [0.0, 0.0, 0.0]);
assert_eq!(c3.volume(), 2.0);
}
}