//! Draw a 3 dimensional shape using solid //! This draws the classic csg example in the wiki on //! [Constructive Solid Geometry](https://en.wikipedia.org/wiki/Constructive_solid_geometry) //! //! >>> cargo run --example csg //! //! Writes an .stl file to target/stl/csg.stl use crater::{ bounding::BoundingBox, csg::{ algebra::CSGAlgebra, marching_cubes::{marching_cubes, MarchingCubesParams}, regions::Region, surfaces::{IntoSurface, Surface3D}, transformations::{RotateAbout, Translate}, }, mesh::MeshCollection, serde::vtk::evaluations::{GeometryEvaluator, MeshColoring}, utils::Parallel, }; fn make_csg() -> Region<3> { let c_r = 1.0; let s_r = 2.0 * c_r; let b_r = 0.7 * s_r; let c1 = -Surface3D::Cylinder { r: c_r }.into_surface(); let c2 = -Surface3D::Cylinder { r: c_r } .into_surface() .transform(RotateAbout(2, 0, std::f64::consts::FRAC_PI_2)); let c3 = -Surface3D::Cylinder { r: c_r } .into_surface() .transform(RotateAbout(2, 1, std::f64::consts::FRAC_PI_2)); let sphere = -Surface3D::Sphere { r: s_r }.into_surface(); let box_sides = ( Surface3D::Plane { normal: [1.0, 0.0, 0.0], } .into_surface() .transform(Translate([b_r, 0.0, 0.0])), Surface3D::Plane { normal: [1.0, 0.0, 0.0], } .into_surface() .transform(Translate([-b_r, 0.0, 0.0])), Surface3D::Plane { normal: [0.0, 1.0, 0.0], } .into_surface() .transform(Translate([0.0, b_r, 0.0])), Surface3D::Plane { normal: [0.0, 1.0, 0.0], } .into_surface() .transform(Translate([0.0, -b_r, 0.0])), Surface3D::Plane { normal: [0.0, 0.0, 1.0], } .into_surface() .transform(Translate([0.0, 0.0, b_r])), Surface3D::Plane { normal: [0.0, 0.0, 1.0], } .into_surface() .transform(Translate([0.0, 0.0, -b_r])), ); let box_region = -box_sides.0 & -(-box_sides.1) & -box_sides.2 & -(-box_sides.3) & -box_sides.4 & -(-box_sides.5); (sphere & box_region) & -(c1 | c2 | c3) } fn main() { // Run marching cubes to render this shape let resolution = 30; let bound = 3.0; let algebra = CSGAlgebra::default(); let params = MarchingCubesParams { region: make_csg(), bounds: BoundingBox { min: [-bound, -bound, -bound], max: [bound, bound, bound], }, resolution: (resolution, resolution, resolution), algebra, }; let mesh: MeshCollection = marching_cubes::<Parallel>(¶ms).into(); let mut path_buf = std::path::PathBuf::from("./target/test_renderings/"); path_buf.push("csg"); path_buf.set_extension("stl"); std::fs::create_dir_all(path_buf.parent().expect("Failed to get parent directory")) .expect("Failed to create directory"); mesh.write_stl(path_buf.to_str().unwrap()) .expect("Failed to write csg.stl"); // VTK let csg = [make_csg()]; let algebra = CSGAlgebra::default(); mesh.to_vtk(Some(&[ Box::new(GeometryEvaluator::Gradients(&csg, &algebra)), Box::new(GeometryEvaluator::Normals(&csg, &algebra)), Box::new(MeshColoring), ])) .export_ascii(path_buf.with_extension("vtk").to_str().unwrap()) .unwrap(); }