Skip to main content

06_loft/
06_loft.rs

1//! Demo of `Solid::loft`: skin a smooth solid through cross-section wires.
2//!
3//! - **Frustum**: two circles of different radii → truncated cone (minimal loft)
4//! - **Morph**: square polygon → circle (cross-section shape transition)
5//! - **Tilted**: three non-parallel circular sections → twisted loft
6
7use cadrum::{DVec3, Edge, Error, Solid};
8
9/// Two circles → frustum (minimal loft example).
10fn build_frustum() -> Result<Solid, Error> {
11	let lower = [Edge::circle(3.0, DVec3::Z)?];
12	let upper = [Edge::circle(1.5, DVec3::Z)?.translate(DVec3::Z * 8.0)];
13	Ok(Solid::loft(&[lower, upper])?.color("#cd853f"))
14}
15
16/// Square polygon → circle (2-section morph loft).
17fn build_morph() -> Result<Solid, Error> {
18	let r = 2.5;
19	let square = Edge::polygon(&[
20		DVec3::new(-r, -r, 0.0),
21		DVec3::new(r, -r, 0.0),
22		DVec3::new(r, r, 0.0),
23		DVec3::new(-r, r, 0.0),
24	])?;
25	let circle = Edge::circle(r, DVec3::Z)?.translate(DVec3::Z * 10.0);
26
27	Ok(Solid::loft([square.as_slice(), std::slice::from_ref(&circle)])?.color("#808000"))
28}
29
30/// Three non-parallel circular sections → twisted loft.
31fn build_tilted() -> Result<Solid, Error> {
32	let bottom = [Edge::circle(2.5, DVec3::Z)?];
33	let mid = [Edge::circle(2.0, DVec3::new(0.3, 0.0, 1.0).normalize())?
34		.translate(DVec3::X + DVec3::Z * 5.0)];
35	let top = [Edge::circle(1.5, DVec3::new(-0.2, 0.3, 1.0).normalize())?
36		.translate(DVec3::new(-0.5, 1.0, 10.0))];
37
38	Ok(Solid::loft(&[bottom, mid, top])?.color("#4682b4"))
39}
40
41fn main() -> Result<(), Error> {
42	let example_name = std::path::Path::new(file!()).file_stem().unwrap().to_str().unwrap();
43
44	let frustum = build_frustum()?;
45	let morph = build_morph()?.translate(DVec3::X * 10.0);
46	let tilted = build_tilted()?.translate(DVec3::X * 20.0);
47
48	let result = [frustum, morph, tilted];
49
50	let mut f = std::fs::File::create(format!("{example_name}.step")).expect("failed to create STEP file");
51	cadrum::write_step(&result, &mut f).expect("failed to write STEP");
52
53	let mut f = std::fs::File::create(format!("{example_name}.svg")).expect("failed to create SVG file");
54	cadrum::mesh(&result, 0.5).and_then(|m| m.write_svg(DVec3::ONE, DVec3::Z, true, false, &mut f)).expect("failed to write SVG");
55
56	println!("wrote {example_name}.step / {example_name}.svg");
57	Ok(())
58}