#[cfg(feature = "output")]
pub mod output;
#[cxx::bridge(namespace = "manifold_rs")]
mod ffi {
unsafe extern "C++" {
include!("manifold_rs.h");
type Polygons;
fn size(self: &Polygons) -> usize;
fn get_as_slice(self: &Polygons, i: usize) -> &[f64];
type Manifold;
fn is_empty(self: &Manifold) -> bool;
fn slice(self: &Manifold, height: f64) -> UniquePtr<Polygons>;
fn project(self: &Manifold) -> UniquePtr<Polygons>;
fn empty() -> UniquePtr<Manifold>;
fn tetrahedron() -> UniquePtr<Manifold>;
fn sphere(radius: f64, segments: u32) -> UniquePtr<Manifold>;
fn cube(x_size: f64, y_size: f64, z_size: f64) -> UniquePtr<Manifold>;
fn cylinder(
radius_low: f64,
radius_high: f64,
height: f64,
segments: u32,
) -> UniquePtr<Manifold>;
fn union_(a: &Manifold, b: &Manifold) -> UniquePtr<Manifold>;
fn intersection(a: &Manifold, b: &Manifold) -> UniquePtr<Manifold>;
fn difference(a: &Manifold, b: &Manifold) -> UniquePtr<Manifold>;
fn trim_by_plane(
self: &Manifold,
x: f64,
y: f64,
z: f64,
offset: f64,
) -> UniquePtr<Manifold>;
fn hull(self: &Manifold) -> UniquePtr<Manifold>;
fn translate(self: &Manifold, x: f64, y: f64, z: f64) -> UniquePtr<Manifold>;
fn scale(self: &Manifold, x: f64, y: f64, z: f64) -> UniquePtr<Manifold>;
fn rotate(self: &Manifold, x: f64, y: f64, z: f64) -> UniquePtr<Manifold>;
fn extrude(
multi_polygon_data: &[&[f64]],
height: f64,
n_divisions: u32,
twist_degrees: f64,
scale_top_x: f64,
scale_top_y: f64,
) -> UniquePtr<Manifold>;
fn revolve(
multi_polygon_data: &[&[f64]],
circular_segments: u32,
revolve_degrees: f64,
) -> UniquePtr<Manifold>;
fn refine(self: &Manifold, n: i32) -> UniquePtr<Manifold>;
fn refine_to_length(self: &Manifold, t: f64) -> UniquePtr<Manifold>;
fn refine_to_tolerance(self: &Manifold, t: f64) -> UniquePtr<Manifold>;
fn smooth_by_normals(self: &Manifold, normal_idx: i32) -> UniquePtr<Manifold>;
fn smooth_out(
self: &Manifold,
min_sharp_angle: f64,
min_smoothness: f64,
) -> UniquePtr<Manifold>;
fn calculate_normals(
self: &Manifold,
normal_idx: i32,
min_sharp_angle: f64,
) -> UniquePtr<Manifold>;
type Mesh;
fn num_props(self: &Mesh) -> u32;
fn vertices(self: &Mesh) -> UniquePtr<CxxVector<f32>>;
fn indices(self: &Mesh) -> UniquePtr<CxxVector<u32>>;
fn mesh_from_manifold(manifold: &Manifold) -> UniquePtr<Mesh>;
fn manifold_from_mesh(mesh: &Mesh) -> UniquePtr<Manifold>;
fn mesh_from_vertices(vertices: &[f32], indices: &[u32]) -> UniquePtr<Mesh>;
}
}
pub enum BooleanOp {
Union,
Intersection,
Difference,
}
pub struct Polygons(cxx::UniquePtr<ffi::Polygons>);
impl Polygons {
pub fn size(&self) -> usize {
self.0.size()
}
pub fn get_as_slice(&self, i: usize) -> &[f64] {
self.0.get_as_slice(i)
}
}
pub struct Manifold(cxx::UniquePtr<ffi::Manifold>);
impl Manifold {
pub fn is_empty(&self) -> bool {
self.0.is_empty()
}
pub fn slice(&self, height: f64) -> Polygons {
Polygons(self.0.slice(height))
}
pub fn project(&self) -> Polygons {
Polygons(self.0.project())
}
pub fn trim_by_plane(&self, x: f64, y: f64, z: f64, offset: f64) -> Self {
Self(self.0.trim_by_plane(x, y, z, offset))
}
pub fn hull(&self) -> Self {
Self(self.0.hull())
}
pub fn translate(&self, x: f64, y: f64, z: f64) -> Self {
Self(self.0.translate(x, y, z))
}
pub fn scale(&self, x: f64, y: f64, z: f64) -> Self {
Self(self.0.scale(x, y, z))
}
pub fn rotate(&self, x: f64, y: f64, z: f64) -> Self {
Self(self.0.rotate(x, y, z))
}
pub fn empty() -> Self {
Self(ffi::empty())
}
pub fn tetrahedron() -> Self {
Self(ffi::tetrahedron())
}
pub fn sphere(radius: f64, segments: u32) -> Self {
Self(ffi::sphere(radius, segments))
}
pub fn cube(x_size: f64, y_size: f64, z_size: f64) -> Self {
Self(ffi::cube(x_size, y_size, z_size))
}
pub fn cylinder(radius_low: f64, radius_high: f64, height: f64, segments: u32) -> Self {
Self(ffi::cylinder(radius_low, radius_high, height, segments))
}
pub fn union(&self, b: &Self) -> Self {
Self(ffi::union_(self.inner(), b.inner()))
}
pub fn intersection(&self, b: &Self) -> Self {
Self(ffi::intersection(self.inner(), b.inner()))
}
pub fn difference(&self, b: &Self) -> Self {
Self(ffi::difference(self.inner(), b.inner()))
}
pub fn boolean_op(&self, b: &Self, op: crate::BooleanOp) -> Self {
match op {
crate::BooleanOp::Union => self.union(b),
crate::BooleanOp::Intersection => self.intersection(b),
crate::BooleanOp::Difference => self.difference(b),
}
}
pub fn extrude(
multi_polygon_data: &[&[f64]],
height: f64,
n_divisions: u32,
twist_degrees: f64,
scale_top_x: f64,
scale_top_y: f64,
) -> Self {
Self(ffi::extrude(
multi_polygon_data,
height,
n_divisions,
twist_degrees,
scale_top_x,
scale_top_y,
))
}
pub fn revolve(
multi_polygon_data: &[&[f64]],
circular_segments: u32,
revolve_degrees: f64,
) -> Self {
Self(ffi::revolve(
multi_polygon_data,
circular_segments,
revolve_degrees,
))
}
pub fn refine(self: &Manifold, n: i32) -> Self {
Self(self.0.refine(n))
}
pub fn refine_to_length(self: &Manifold, t: f64) -> Self {
Self(self.0.refine_to_length(t))
}
pub fn refine_to_tolerance(self: &Manifold, t: f64) -> Self {
Self(self.0.refine_to_tolerance(t))
}
pub fn smooth_by_normals(self: &Manifold, normal_idx: i32) -> Self {
Self(self.0.smooth_by_normals(normal_idx))
}
pub fn smooth_out(self: &Manifold, min_sharp_angle: f64, min_smoothness: f64) -> Self {
Self(self.0.smooth_out(min_sharp_angle, min_smoothness))
}
pub fn calculate_normals(self: &Manifold, normal_idx: i32, min_sharp_angle: f64) -> Self {
Self(self.0.calculate_normals(normal_idx, min_sharp_angle))
}
pub fn to_mesh(&self) -> Mesh {
Mesh(ffi::mesh_from_manifold(&self.0))
}
pub fn from_mesh(mesh: Mesh) -> Self {
mesh.into()
}
fn inner(&self) -> &ffi::Manifold {
self.0.as_ref().unwrap()
}
}
pub struct Mesh(cxx::UniquePtr<ffi::Mesh>);
impl Mesh {
pub fn new(vertices: &[f32], indices: &[u32]) -> Self {
let mesh = ffi::mesh_from_vertices(vertices, indices);
Self(mesh)
}
pub fn num_props(&self) -> u32 {
self.0.num_props()
}
pub fn vertices(&self) -> Vec<f32> {
let vertices_binding = self.0.vertices();
let vertices = vertices_binding.as_ref().unwrap().as_slice();
vertices.to_vec()
}
pub fn indices(&self) -> Vec<u32> {
let indices_binding = self.0.indices();
let indices = indices_binding.as_ref().unwrap().as_slice();
indices.to_vec()
}
pub fn to_manifold(&self) -> Manifold {
let manifold = ffi::manifold_from_mesh(&self.0);
Manifold(manifold)
}
}
impl From<Mesh> for Manifold {
fn from(mesh: Mesh) -> Self {
mesh.to_manifold()
}
}
impl From<Manifold> for Mesh {
fn from(manifold: Manifold) -> Self {
manifold.to_mesh()
}
}
#[test]
fn test_manifold_ffi() {
let sphere = ffi::sphere(1.0, 32);
let mesh = ffi::mesh_from_manifold(&sphere);
let vertices_binding = mesh.vertices();
let vertices = vertices_binding.as_ref().unwrap().as_slice();
assert!(!vertices.is_empty());
let indices_binding = mesh.indices();
let indices = indices_binding.as_ref().unwrap().as_slice();
assert!(!indices.is_empty());
}