diff --git a/Cargo.lock b/Cargo.lock index be5be38c4..bdf80e687 100644 --- a/Cargo.lock +++ b/Cargo.lock @@ -686,6 +686,8 @@ checksum = "43da5946c66ffcc7745f48db692ffbb10a83bfe0afd96235c5c2a4fb23994929" name = "cuboid" version = "0.1.0" dependencies = [ + "anyhow", + "clap", "fj", ] @@ -1362,7 +1364,8 @@ checksum = "dfa686283ad6dd069f105e5ab091b04c62850d3e4cf5d67debad1933f55023df" name = "holes" version = "0.1.0" dependencies = [ - "cuboid", + "anyhow", + "clap", "fj", ] @@ -3426,6 +3429,8 @@ dependencies = [ name = "spacer" version = "0.1.0" dependencies = [ + "anyhow", + "clap", "fj", ] @@ -3468,6 +3473,8 @@ checksum = "a8f112729512f8e442d81f95a8a7ddf2b7c6b8a1a6f509a95864142b30cab2d3" name = "star" version = "0.1.0" dependencies = [ + "anyhow", + "clap", "fj", ] diff --git a/crates/fj/src/instance.rs b/crates/fj/src/instance.rs index ba0900b08..63bf910eb 100644 --- a/crates/fj/src/instance.rs +++ b/crates/fj/src/instance.rs @@ -94,6 +94,59 @@ impl Instance { Ok(()) } + + /// Process a model with pre-parsed arguments + /// + /// This function is similar to [`process_model`], but accepts pre-parsed arguments + /// instead of parsing them from the command line. This is useful when you want to + /// extend the standard arguments with your own parameters. + pub fn process_model_args(&mut self, model: &M, args: Args) -> Result + where + for<'r> (&'r M, Tolerance): Triangulate, + for<'r> &'r M: BoundingVolume<3>, + { + tracing_subscriber::registry() + .with(tracing_subscriber::fmt::layer()) + .with(tracing_subscriber::EnvFilter::from_default_env()) + .init(); + + if !args.ignore_validation { + self.core.layers.validation.take_errors()?; + } + + let aabb = model.aabb(&self.core.layers.geometry).unwrap_or(Aabb { + min: Point::origin(), + max: Point::origin(), + }); + + let tolerance = match args.tolerance { + None => { + let mut min_extent = Scalar::MAX; + for extent in aabb.size().components { + if extent > Scalar::ZERO && extent < min_extent { + min_extent = extent; + } + } + + let tolerance = min_extent / Scalar::from_f64(1000.); + Tolerance::from_scalar(tolerance)? + } + Some(user_defined_tolerance) => user_defined_tolerance, + }; + + let tri_mesh = (model, tolerance).triangulate(&mut self.core); + + if let Some(path) = args.export { + export::export(tri_mesh.all_triangles(), &path)?; + return Ok(()); + } + + make_viewer_and_spawn_thread(|viewer| { + viewer.display_model(tri_mesh); + })?; + + Ok(()) + } } /// Return value of [`Instance::process_model`] diff --git a/models/cuboid/Cargo.toml b/models/cuboid/Cargo.toml index 42746d61c..f5b334b92 100644 --- a/models/cuboid/Cargo.toml +++ b/models/cuboid/Cargo.toml @@ -3,5 +3,11 @@ name = "cuboid" version = "0.1.0" edition = "2021" -[dependencies.fj] -path = "../../crates/fj" +[[bin]] +name = "cuboid" +path = "src/main.rs" + +[dependencies] +fj = { path = "../../crates/fj" } +clap = { version = "4.5", features = ["derive"] } +anyhow = "1.0" diff --git a/models/cuboid/src/main.rs b/models/cuboid/src/main.rs index 3fc949f16..703ae6100 100644 --- a/models/cuboid/src/main.rs +++ b/models/cuboid/src/main.rs @@ -1,6 +1,31 @@ -fn main() -> fj::Result { - let mut fj = fj::Instance::new(); - let model = cuboid::model([3., 2., 1.], &mut fj.core); - fj.process_model(&model)?; +use clap::Parser; +use fj::{Args, Instance}; + +#[derive(Parser)] +struct Parameters { + /// Size of the cuboid, as a comma-separated vector `x,y,z` + #[arg(long, value_parser = parse_vector_3)] + size: [f64; 3], + + #[command(flatten)] + fj: Args, +} + +fn parse_vector_3(arg: &str) -> anyhow::Result<[f64; 3]> { + Ok(arg + .split(',') + .map(str::parse) + .collect::, _>>()? + .as_slice() + .try_into()?) +} + +fn main() -> anyhow::Result<()> { + let mut fj = Instance::new(); + let params = Parameters::parse(); + + let model = cuboid::model(params.size, &mut fj.core); + fj.process_model_args(&model, params.fj)?; + Ok(()) } diff --git a/models/holes/Cargo.toml b/models/holes/Cargo.toml index 5f90cc33a..9b5cacaca 100644 --- a/models/holes/Cargo.toml +++ b/models/holes/Cargo.toml @@ -3,8 +3,11 @@ name = "holes" version = "0.1.0" edition = "2021" -[dependencies.fj] -path = "../../crates/fj" +[[bin]] +name = "holes" +path = "src/main.rs" -[dependencies.cuboid] -path = "../cuboid" +[dependencies] +fj = { path = "../../crates/fj" } +clap = { version = "4.5", features = ["derive"] } +anyhow = "1.0" diff --git a/models/holes/src/main.rs b/models/holes/src/main.rs index 336c30c2a..2c2e83f34 100644 --- a/models/holes/src/main.rs +++ b/models/holes/src/main.rs @@ -1,6 +1,23 @@ -fn main() -> fj::Result { - let mut fj = fj::Instance::new(); - let model = holes::model(0.25, &mut fj.core); - fj.process_model(&model)?; +use anyhow::Result; +use clap::Parser; +use fj::{Args, Instance}; + +#[derive(Parser)] +struct Parameters { + /// Radius of the holes + #[arg(long, default_value = "0.25")] + radius: f64, + + #[command(flatten)] + fj: Args, +} + +fn main() -> Result<()> { + let mut fj = Instance::new(); + let params = Parameters::parse(); + + let model = holes::model(params.radius, &mut fj.core); + fj.process_model_args(&model, params.fj)?; + Ok(()) } diff --git a/models/spacer/Cargo.toml b/models/spacer/Cargo.toml index a83c4c299..1a321051b 100644 --- a/models/spacer/Cargo.toml +++ b/models/spacer/Cargo.toml @@ -3,5 +3,11 @@ name = "spacer" version = "0.1.0" edition = "2021" -[dependencies.fj] -path = "../../crates/fj" +[[bin]] +name = "spacer" +path = "src/main.rs" + +[dependencies] +fj = { path = "../../crates/fj" } +clap = { version = "4.5", features = ["derive"] } +anyhow = "1.0" diff --git a/models/spacer/src/main.rs b/models/spacer/src/main.rs index 078a7a764..26d0bc78b 100644 --- a/models/spacer/src/main.rs +++ b/models/spacer/src/main.rs @@ -1,6 +1,36 @@ -fn main() -> fj::Result { - let mut fj = fj::Instance::new(); - let model = spacer::model(1., 0.5, 1., &mut fj.core); - fj.process_model(&model)?; +use anyhow::Result; +use clap::Parser; +use fj::{Args, Instance}; + +#[derive(Parser)] +struct Parameters { + /// Outer radius of the spacer + #[arg(long, default_value = "1.0")] + outer_radius: f64, + + /// Inner radius of the spacer + #[arg(long, default_value = "0.5")] + inner_radius: f64, + + /// Height of the spacer + #[arg(long, default_value = "1.0")] + height: f64, + + #[command(flatten)] + fj: Args, +} + +fn main() -> Result<()> { + let mut fj = Instance::new(); + let params = Parameters::parse(); + + let model = spacer::model( + params.outer_radius, + params.inner_radius, + params.height, + &mut fj.core, + ); + fj.process_model_args(&model, params.fj)?; + Ok(()) } diff --git a/models/star/Cargo.toml b/models/star/Cargo.toml index 0279bef41..c205fd4f7 100644 --- a/models/star/Cargo.toml +++ b/models/star/Cargo.toml @@ -3,5 +3,11 @@ name = "star" version = "0.1.0" edition = "2021" -[dependencies.fj] -path = "../../crates/fj" +[[bin]] +name = "star" +path = "src/main.rs" + +[dependencies] +fj = { path = "../../crates/fj" } +clap = { version = "4.5", features = ["derive"] } +anyhow = "1.0" diff --git a/models/star/src/main.rs b/models/star/src/main.rs index 4e9baff2e..d44ea64e1 100644 --- a/models/star/src/main.rs +++ b/models/star/src/main.rs @@ -1,6 +1,41 @@ -fn main() -> fj::Result { - let mut fj = fj::Instance::new(); - let model = star::model(5, 1., 2., 1., &mut fj.core); - fj.process_model(&model)?; +use anyhow::Result; +use clap::Parser; +use fj::{Args, Instance}; + +#[derive(Parser)] +struct Parameters { + /// Number of points in the star + #[arg(long, default_value = "5")] + points: u64, + + /// Inner radius of the star + #[arg(long, default_value = "1.0")] + inner_radius: f64, + + /// Outer radius of the star + #[arg(long, default_value = "2.0")] + outer_radius: f64, + + /// Height of the star + #[arg(long, default_value = "1.0")] + height: f64, + + #[command(flatten)] + fj: Args, +} + +fn main() -> Result<()> { + let mut fj = Instance::new(); + let params = Parameters::parse(); + + let model = star::model( + params.points, + params.inner_radius, + params.outer_radius, + params.height, + &mut fj.core, + ); + fj.process_model_args(&model, params.fj)?; + Ok(()) }