rscad_csg_bsp/primitives/
torus.rs1use crate::*;
2use nalgebra::Point;
3
4pub fn torus<T: Number>(
11 major_radius: T,
12 minor_radius: T,
13 major_segments: usize,
14 minor_segments: usize,
15) -> Csg<T> {
16 let major_segments = major_segments.max(3);
17 let minor_segments = minor_segments.max(3);
18 let two_pi = T::PI() + T::PI();
19 let maj_t = T::from(major_segments).expect("BUG: segment count is representable as T");
20 let min_t = T::from(minor_segments).expect("BUG: segment count is representable as T");
21
22 let vertex = |i: usize, j: usize| -> Point<T, 3> {
23 let theta = two_pi * T::from(i).expect("BUG: loop index is representable as T") / maj_t;
24 let phi = two_pi * T::from(j).expect("BUG: loop index is representable as T") / min_t;
25 let r = major_radius + minor_radius * num_traits::real::Real::cos(phi);
26 Point::from([
27 r * num_traits::real::Real::cos(theta),
28 minor_radius * num_traits::real::Real::sin(phi),
29 r * num_traits::real::Real::sin(theta),
30 ])
31 };
32
33 let mut polygons = Vec::with_capacity(major_segments * minor_segments);
34
35 for i in 0..major_segments {
36 let in_ = (i + 1) % major_segments;
37 for j in 0..minor_segments {
38 let jn = (j + 1) % minor_segments;
39
40 let v00 = vertex(i, j);
41 let v01 = vertex(i, jn);
42 let v10 = vertex(in_, j);
43 let v11 = vertex(in_, jn);
44
45 if let Ok(p) = Polygon::from_points(vec![v00, v01, v11, v10]) {
46 polygons.push(p);
47 }
48 }
49 }
50
51 Csg::from_polygons(polygons)
52}