Cylinder
Build a cylinder with rsweep, try_attach_plane, and tsweep
What happens at each step
- Rotational sweep (`rsweep`): spin a vertex to make a circular wire.
- Plane attachment: cap the wire into a disk with
try_attach_plane. - Translational sweep (`tsweep`): extrude the disk to form the solid.
src/cylinder.rs
#![allow(unused)] fn main() { use truck_modeling::*; }
#![allow(unused)] fn main() { pub fn cylinder() -> Solid { // STEPS 1-4 GO HERE } }
1. Place a vertex on the base circle at (0, 0, -1).
#![allow(unused)] fn main() { let vertex: Vertex = builder::vertex(Point3::new(0.0, 0.0, -1.0)); }
visual
y
│
│
● │ (start at z = -1)
│
└──── x
/
z
2. Spin the vertex around +Z to form a circular wire.
#![allow(unused)] fn main() { let circle: Wire = builder::rsweep( &vertex, Point3::new(0.0, 1.0, -1.0), // point on rotation axis Vector3::unit_z(), // axis direction Rad(7.0), // > 2π ensures closure ); }
visual
Axis: +Z through (0, 1, -1)
●---●---● (circle in XY plane at z = -1)
\ | /
\ | /
+
axis
3. Cap the wire into a planar disk.
#![allow(unused)] fn main() { let disk: Face = builder::try_attach_plane(&vec![circle]).expect("cannot attach plane"); }
visual
The circular wire is filled to a disk (face) if the wire is closed and planar.
+------+
/ \
| ● |
\ /
+------+
4. Extrude the disk 2 units along +Z to make the solid.
#![allow(unused)] fn main() { builder::tsweep(&disk, 2.0 * Vector3::unit_z()) }
visual
Sweeping the disk upward (+Z) forms the cylinder volume:
●───────●
/| /|
●───────● |
| | | |
| ●──────|-●
|/ |/
●───────●
Update src/lib.rs to expose cylinder
#![allow(unused)] fn main() { pub mod cylinder; pub use cylinder::cylinder; }
Keep helpers in lib.rs and cylinder in src/cylinder.rs.
Example entry point
examples/cylinder.rs stays tiny and calls into the library:
fn main() { let cylinder = truck_brep::cylinder(); truck_brep::save_obj(&cylinder, "output/cylinder.obj").unwrap(); truck_brep::save_step(&cylinder, "output/cylinder.step").unwrap(); }
Directory tree (for this section)
truck_brep/
├─ src/
│ ├─ lib.rs # helpers + re-exports
│ ├─ cube.rs
│ ├─ torus.rs
│ └─ cylinder.rs # this section
├─ examples/
│ ├─ cube.rs
│ ├─ torus.rs
│ └─ cylinder.rs
└─ output/ # created at runtime
Complete code
src/lib.rs
#![allow(unused)] fn main() { use std::{fs, io, path::Path}; use truck_meshalgo::prelude::*; use truck_modeling::*; use truck_stepio::out::{CompleteStepDisplay, StepModel}; use truck_topology::compress::{CompressedShell, CompressedSolid}; pub mod cube; pub use cube::cube; pub mod torus; pub use torus::torus; pub mod cylinder; pub use cylinder::cylinder; /// Helper to compress modeling shapes into STEP-compatible data. pub trait StepCompress { type Compressed; fn compress_for_step(&self) -> Self::Compressed; } impl StepCompress for Shell { type Compressed = CompressedShell<Point3, Curve, Surface>; fn compress_for_step(&self) -> Self::Compressed { self.compress() } } impl StepCompress for Solid { type Compressed = CompressedSolid<Point3, Curve, Surface>; fn compress_for_step(&self) -> Self::Compressed { self.compress() } } /// Export any B-rep (Solid or Shell) to STEP. pub fn save_step<T, P>(brep: &T, path: P) -> io::Result<()> where T: StepCompress, for<'a> StepModel<'a, Point3, Curve, Surface>: From<&'a T::Compressed>, P: AsRef<Path>, { let path = path.as_ref(); if let Some(parent) = path.parent() { fs::create_dir_all(parent)?; } let compressed = brep.compress_for_step(); let display = CompleteStepDisplay::new( StepModel::from(&compressed), Default::default(), ); fs::write(path, display.to_string()) } /// Triangulate any B-rep (Solid or Shell) and write an OBJ mesh. pub fn save_obj(shape: &impl MeshableShape, path: impl AsRef<Path>) -> io::Result<()> { let mesh = shape.triangulation(0.01).to_polygon(); let path = path.as_ref(); if let Some(parent) = path.parent() { fs::create_dir_all(parent)?; } let mut obj = fs::File::create(path)?; obj::write(&mesh, &mut obj).map_err(|err| io::Error::new(io::ErrorKind::Other, err)) } }
src/cylinder.rs
#![allow(unused)] fn main() { use truck_modeling::*; pub fn cylinder() -> Solid { let vertex: Vertex = builder::vertex(Point3::new(0.0, 0.0, -1.0)); let circle: Wire = builder::rsweep( &vertex, Point3::new(0.0, 1.0, -1.0), Vector3::unit_z(), Rad(7.0), ); let disk: Face = builder::try_attach_plane(&vec![circle]).expect("cannot attach plane"); builder::tsweep(&disk, 2.0 * Vector3::unit_z()) } }
examples/cylinder.rs
fn main() { let cylinder = truck_brep::cylinder(); truck_brep::save_obj(&cylinder, "output/cylinder.obj").unwrap(); truck_brep::save_step(&cylinder, "output/cylinder.step").unwrap(); }