#[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_sphere;
#[rust_name = "new_wall_sphere"]
fn construct(
xc_: f64,
yc_: f64,
zc_: f64,
rc_: f64,
w_id_: i32,
) -> UniquePtr<wall_sphere>;
#[rust_name = "clone_wall_sphere"]
fn clone_wall(
value: &UniquePtr<wall_sphere>,
) -> UniquePtr<wall_sphere>;
fn point_inside(
self: Pin<&mut wall_sphere>,
x: f64,
y: f64,
z: f64,
) -> bool;
#[rust_name = "cut_cell_0"]
fn cut_cell(
self: Pin<&mut wall_sphere>,
c: Pin<&mut voronoicell>,
x: f64,
y: f64,
z: f64,
) -> bool;
#[rust_name = "cut_cell_1"]
fn cut_cell(
self: Pin<&mut wall_sphere>,
c: Pin<&mut voronoicell_neighbor>,
x: f64,
y: f64,
z: f64,
) -> bool;
type wall_plane;
#[rust_name = "new_wall_plane"]
fn construct(
xc_: f64,
yc_: f64,
zc_: f64,
rc_: f64,
w_id_: i32,
) -> UniquePtr<wall_plane>;
#[rust_name = "clone_wall_plane"]
fn clone_wall(
value: &UniquePtr<wall_plane>,
) -> UniquePtr<wall_plane>;
fn point_inside(
self: Pin<&mut wall_plane>,
x: f64,
y: f64,
z: f64,
) -> bool;
#[rust_name = "cut_cell_0"]
fn cut_cell(
self: Pin<&mut wall_plane>,
c: Pin<&mut voronoicell>,
x: f64,
y: f64,
z: f64,
) -> bool;
#[rust_name = "cut_cell_1"]
fn cut_cell(
self: Pin<&mut wall_plane>,
c: Pin<&mut voronoicell_neighbor>,
x: f64,
y: f64,
z: f64,
) -> bool;
type wall_cylinder;
#[rust_name = "new_wall_cylinder"]
fn construct(
xc_: f64,
yc_: f64,
zc_: f64,
xa_: f64,
ya_: f64,
za_: f64,
rc_: f64,
w_id_: i32,
) -> UniquePtr<wall_cylinder>;
#[rust_name = "clone_wall_cylinder"]
fn clone_wall(
value: &UniquePtr<wall_cylinder>,
) -> UniquePtr<wall_cylinder>;
fn point_inside(
self: Pin<&mut wall_cylinder>,
x: f64,
y: f64,
z: f64,
) -> bool;
#[rust_name = "cut_cell_0"]
fn cut_cell(
self: Pin<&mut wall_cylinder>,
c: Pin<&mut voronoicell>,
x: f64,
y: f64,
z: f64,
) -> bool;
#[rust_name = "cut_cell_1"]
fn cut_cell(
self: Pin<&mut wall_cylinder>,
c: Pin<&mut voronoicell_neighbor>,
x: f64,
y: f64,
z: f64,
) -> bool;
type wall_cone;
#[rust_name = "new_wall_cone"]
fn construct(
xc_: f64,
yc_: f64,
zc_: f64,
xa_: f64,
ya_: f64,
za_: f64,
ang: f64,
w_id_: i32,
) -> UniquePtr<wall_cone>;
#[rust_name = "clone_wall_cone"]
fn clone_wall(
value: &UniquePtr<wall_cone>,
) -> UniquePtr<wall_cone>;
fn point_inside(
self: Pin<&mut wall_cone>,
x: f64,
y: f64,
z: f64,
) -> bool;
#[rust_name = "cut_cell_0"]
fn cut_cell(
self: Pin<&mut wall_cone>,
c: Pin<&mut voronoicell>,
x: f64,
y: f64,
z: f64,
) -> bool;
#[rust_name = "cut_cell_1"]
fn cut_cell(
self: Pin<&mut wall_cone>,
c: Pin<&mut voronoicell_neighbor>,
x: f64,
y: f64,
z: f64,
) -> bool;
type wall;
fn wall_sphere_to_wall<'a>(
w: Pin<&'a mut wall_sphere>,
) -> Pin<&'a mut wall>;
fn wall_plane_to_wall<'a>(
w: Pin<&'a mut wall_plane>,
) -> Pin<&'a mut wall>;
fn wall_cylinder_to_wall<'a>(
w: Pin<&'a mut wall_cylinder>,
) -> Pin<&'a mut wall>;
fn wall_cone_to_wall<'a>(
w: Pin<&'a mut wall_cone>,
) -> Pin<&'a mut wall>;
}
}
use crate::prelude::{VoroCell, VoroCellNbr, VoroCellSgl};
use cxx::UniquePtr;
type DVec3 = [f64; 3];
pub struct WallSphere {
pub(crate) inner: UniquePtr<ffi::wall_sphere>,
}
impl WallSphere {
pub fn new(c: DVec3, r: f64) -> Self {
Self::new_with_id(c, r, -99)
}
pub fn new_with_id(c: DVec3, r: f64, id: i32) -> Self {
Self {
inner: ffi::new_wall_sphere(
c[0], c[1], c[2], r, id,
),
}
}
}
pub struct WallPlane {
pub(crate) inner: UniquePtr<ffi::wall_plane>,
}
impl WallPlane {
pub fn new(c: DVec3, a: f64) -> Self {
Self::new_with_id(c, a, -99)
}
pub fn new_with_id(c: DVec3, a: f64, id: i32) -> Self {
Self {
inner: ffi::new_wall_plane(
c[0], c[1], c[2], a, id,
),
}
}
}
pub struct WallCylinder {
pub(crate) inner: UniquePtr<ffi::wall_cylinder>,
}
impl WallCylinder {
pub fn new(c: DVec3, a: DVec3, r: f64) -> Self {
Self::new_with_id(c, a, r, -99)
}
pub fn new_with_id(
c: DVec3,
a: DVec3,
r: f64,
id: i32,
) -> Self {
Self {
inner: ffi::new_wall_cylinder(
c[0], c[1], c[2], a[0], a[1], a[2], r, id,
),
}
}
}
pub struct WallCone {
pub(crate) inner: UniquePtr<ffi::wall_cone>,
}
impl WallCone {
pub fn new(c: DVec3, a: DVec3, ang: f64) -> Self {
Self::new_with_id(c, a, ang, -99)
}
pub fn new_with_id(
c: DVec3,
a: DVec3,
ang: f64,
id: i32,
) -> Self {
Self {
inner: ffi::new_wall_cone(
c[0], c[1], c[2], a[0], a[1], a[2], ang, id,
),
}
}
}
impl Clone for WallSphere {
fn clone(&self) -> Self {
Self {
inner: ffi::clone_wall_sphere(&self.inner),
}
}
}
impl Clone for WallPlane {
fn clone(&self) -> Self {
Self {
inner: ffi::clone_wall_plane(&self.inner),
}
}
}
impl Clone for WallCylinder {
fn clone(&self) -> Self {
Self {
inner: ffi::clone_wall_cylinder(&self.inner),
}
}
}
impl Clone for WallCone {
fn clone(&self) -> Self {
Self {
inner: ffi::clone_wall_cone(&self.inner),
}
}
}
pub trait Wall0 {
fn point_inside(&mut self, xyz: DVec3) -> bool;
}
impl Wall0 for WallSphere {
fn point_inside(&mut self, xyz: DVec3) -> bool {
self.inner
.pin_mut()
.point_inside(xyz[0], xyz[1], xyz[2])
}
}
impl Wall0 for WallPlane {
fn point_inside(&mut self, xyz: DVec3) -> bool {
self.inner
.pin_mut()
.point_inside(xyz[0], xyz[1], xyz[2])
}
}
impl Wall0 for WallCylinder {
fn point_inside(&mut self, xyz: DVec3) -> bool {
self.inner
.pin_mut()
.point_inside(xyz[0], xyz[1], xyz[2])
}
}
impl Wall0 for WallCone {
fn point_inside(&mut self, xyz: DVec3) -> bool {
self.inner
.pin_mut()
.point_inside(xyz[0], xyz[1], xyz[2])
}
}
pub trait Wall1<T: VoroCell> {
fn cut_cell(
&mut self,
cell: &mut T,
xyz: DVec3,
) -> bool;
}
impl Wall1<VoroCellSgl> for WallSphere {
fn cut_cell(
&mut self,
cell: &mut VoroCellSgl,
xyz: DVec3,
) -> bool {
self.inner.pin_mut().cut_cell_0(
cell.inner.pin_mut(),
xyz[0],
xyz[1],
xyz[2],
)
}
}
impl Wall1<VoroCellNbr> for WallSphere {
fn cut_cell(
&mut self,
cell: &mut VoroCellNbr,
xyz: DVec3,
) -> bool {
self.inner.pin_mut().cut_cell_1(
cell.inner.pin_mut(),
xyz[0],
xyz[1],
xyz[2],
)
}
}
impl Wall1<VoroCellSgl> for WallPlane {
fn cut_cell(
&mut self,
cell: &mut VoroCellSgl,
xyz: DVec3,
) -> bool {
self.inner.pin_mut().cut_cell_0(
cell.inner.pin_mut(),
xyz[0],
xyz[1],
xyz[2],
)
}
}
impl Wall1<VoroCellNbr> for WallPlane {
fn cut_cell(
&mut self,
cell: &mut VoroCellNbr,
xyz: DVec3,
) -> bool {
self.inner.pin_mut().cut_cell_1(
cell.inner.pin_mut(),
xyz[0],
xyz[1],
xyz[2],
)
}
}
impl Wall1<VoroCellSgl> for WallCylinder {
fn cut_cell(
&mut self,
cell: &mut VoroCellSgl,
xyz: DVec3,
) -> bool {
self.inner.pin_mut().cut_cell_0(
cell.inner.pin_mut(),
xyz[0],
xyz[1],
xyz[2],
)
}
}
impl Wall1<VoroCellNbr> for WallCylinder {
fn cut_cell(
&mut self,
cell: &mut VoroCellNbr,
xyz: DVec3,
) -> bool {
self.inner.pin_mut().cut_cell_1(
cell.inner.pin_mut(),
xyz[0],
xyz[1],
xyz[2],
)
}
}
impl Wall1<VoroCellSgl> for WallCone {
fn cut_cell(
&mut self,
cell: &mut VoroCellSgl,
xyz: DVec3,
) -> bool {
self.inner.pin_mut().cut_cell_0(
cell.inner.pin_mut(),
xyz[0],
xyz[1],
xyz[2],
)
}
}
impl Wall1<VoroCellNbr> for WallCone {
fn cut_cell(
&mut self,
cell: &mut VoroCellNbr,
xyz: DVec3,
) -> bool {
self.inner.pin_mut().cut_cell_1(
cell.inner.pin_mut(),
xyz[0],
xyz[1],
xyz[2],
)
}
}
pub trait Wall:
Wall0 + Wall1<VoroCellSgl> + Wall1<VoroCellNbr>
{
}
impl Wall for WallSphere {}
impl Wall for WallPlane {}
impl Wall for WallCylinder {}
impl Wall for WallCone {}
#[cfg(test)]
mod tests {
use super::*;
use crate::prelude::{VoroCell, VoroCellSgl};
#[test]
fn basic_test() {
let mut w0 =
WallSphere::new([10.0, 0.0, 0.0], 10.0);
let mut c0 = VoroCellSgl::new(
[-1.0, -1.0, -1.0],
[1.0, 1.0, 1.0],
);
assert_eq!(c0.volume(), 8.0);
let mut c1 = c0.clone();
assert_eq!(c1.volume(), 8.0);
let b = w0.cut_cell(&mut c1, [0.0, 0.0, 0.0]);
assert_eq!(c0.volume(), 8.0);
assert_eq!(c1.volume(), 4.0);
assert_eq!(b, true);
let mut w1 = w0.clone();
let c = w1.cut_cell(&mut c0, [0.0, 0.0, 0.0]);
assert_eq!(c0.volume(), 4.0);
assert_eq!(c, true);
}
#[test]
fn test_nbr() {
let mut w0 =
WallSphere::new([10.0, 0.0, 0.0], 10.0);
let mut c0 = VoroCellNbr::new(
[-1.0, -1.0, -1.0],
[1.0, 1.0, 1.0],
);
w0.cut_cell(&mut c0, [0.0, 0.0, 0.0]);
assert_eq!(c0.volume(), 4.0);
}
#[test]
fn overload_test() {
let mut w0 =
WallSphere::new([10.0, 0.0, 0.0], 10.0);
let mut c0 = VoroCellSgl::new(
[-1.0, -1.0, -1.0],
[1.0, 1.0, 1.0],
);
let mut c1 = VoroCellSgl::new(
[-1.0, -1.0, -1.0],
[1.0, 1.0, 1.0],
);
w0.cut_cell(&mut c0, [0.0, 0.0, 0.0]);
w0.cut_cell(&mut c1, [0.0, 0.0, 0.0]);
}
#[test]
fn all_types() {
WallPlane::new([10.0, 0.0, 0.0], 10.0);
WallPlane::new([1.0, 0.0, 0.0], 10.0);
WallCylinder::new(
[0.0, 0.0, 0.0],
[1.0, 0.0, 0.0],
10.0,
);
WallCone::new(
[0.0, 0.0, 0.0],
[1.0, 0.0, 0.0],
1.0,
);
}
}