//! Draw a 3 dimensional heart using solid
//!
//! >>> cargo run --example heart
//!
//! Writes an .stl file to target/stl/heart.stl

use crater::{
    bounding::BoundingBox,
    csg::{
        algebra::CSGAlgebra,
        marching_cubes::{marching_cubes, MarchingCubesParams},
        regions::{Region, Side},
        surfaces::{IntoSurface, Surface, Surface3D},
        transformations::{ScaleDim, Translate},
    },
    mesh::MeshCollection,
    utils::Parallel,
};

fn main() {
    let heart = -Surface::parse_str("x^2 + (-y + (x^2)^(1.0/3.0))^2 - 50")
        .unwrap()
        .transform(ScaleDim(0, 0.2))
        .transform(ScaleDim(1, 0.2))
        .transform(ScaleDim(2, 0.2));

    let z0 = Region::HalfSpace(
        Surface3D::Plane {
            normal: [0.0, 0.0, 1.0],
        }
        .into_surface(),
        Side::Positive,
    );
    let z1 = -Surface3D::Plane {
        normal: [0.0, 0.0, 1.0],
    }
    .into_surface()
    .transform(Translate([0.0, 0.0, 1.0]));

    let csg = heart & z0 & z1;
    let resolution = 50;
    let bound = 3.0;
    let params = MarchingCubesParams {
        region: csg,
        bounds: BoundingBox {
            min: [-bound, -bound, -bound],
            max: [bound, bound, bound],
        },
        resolution: (resolution, resolution, resolution),
        algebra: CSGAlgebra::default(),
    };
    let mesh: MeshCollection = marching_cubes::<Parallel>(&params).into();
    let mut path_buf = std::path::PathBuf::from("./target/test_renderings/");
    path_buf.push("heart");
    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");
}