use super::{
ErrorWrapper,
io::{extension, invalid_output, read_mesh, write_mesh, write_segmentation},
};
use conspire::geometry::{grid::Voxels, mesh::Mesh};
use std::time::Instant;
#[derive(clap::Args)]
pub struct SegmentArgs {
#[arg(long, short, value_name = "FILE")]
pub input: String,
#[arg(long, short, value_name = "FILE")]
pub output: String,
#[arg(default_value_t = 1, long, short = 'g', value_name = "NUM")]
pub grid: usize,
#[arg(long, short = 's', value_name = "NUM")]
pub size: f64,
#[arg(long, num_args = 1.., short, value_delimiter = ' ', value_name = "ID")]
pub remove: Option<Vec<usize>>,
}
pub fn segment(args: SegmentArgs, quiet: bool) -> Result<(), ErrorWrapper> {
let mesh = read_mesh(&args.input, quiet, true)?;
let time = Instant::now();
crate::echo!(quiet, " \x1b[1;96mSegmenting\x1b[0m from finite elements");
let voxels = Voxels::<usize>::from_finite_elements(&mesh, args.size);
let nel = *voxels.nel();
let remove = args.remove.unwrap_or_default();
let data: Vec<u8> = voxels
.data()
.iter()
.map(|&block| {
if remove.contains(&block) {
0
} else {
block as u8
}
})
.collect();
let voxels = Voxels::<u8>::new(data, nel);
crate::echo!(quiet, " \x1b[1;92mDone\x1b[0m {:?}", time.elapsed());
match extension(&args.output) {
Some("npy") | Some("spn") | Some("vti") => write_segmentation(&args.output, &voxels, quiet),
Some("exo") | Some("inp") | Some("mesh") | Some("vtu") => {
let mesh = Mesh::from_voxels(voxels, Some(&[0u8]));
write_mesh(&args.output, mesh, quiet)
}
extension => Err(invalid_output(&args.output, extension)),
}
}