rscad_csg_bsp/primitives/
cone.rs1use crate::*;
2use nalgebra::{Point, Vector3};
3
4pub fn cone<T: Number>(radius: T, height: T, segments: usize) -> Csg<T> {
10 let segments = segments.max(3);
11 let two = T::one() + T::one();
12 let half_h = height / two;
13 let two_pi = two * T::PI();
14 let seg_t = T::from(segments).expect("BUG: segment count is representable as T");
15
16 let apex = Point::from([T::zero(), half_h, T::zero()]);
17
18 let base: Vec<Point<T, 3>> = (0..segments)
19 .map(|j| {
20 let angle = two_pi * T::from(j).expect("BUG: loop index is representable as T") / seg_t;
21 Point::from([
22 radius * num_traits::real::Real::cos(angle),
23 -half_h,
24 radius * num_traits::real::Real::sin(angle),
25 ])
26 })
27 .collect();
28
29 let mut polygons = Vec::new();
30
31 let mut base_cap = base.clone();
33 base_cap.reverse();
34 if let Ok(p) = Polygon::from_points_and_plane(base_cap, Plane::new(-Vector3::y(), half_h)) {
35 polygons.push(p);
36 }
37
38 for j in 0..segments {
40 let jn = (j + 1) % segments;
41 if let Ok(p) = Polygon::from_points(vec![apex, base[jn], base[j]]) {
42 polygons.push(p);
43 }
44 }
45
46 Csg::from_polygons(polygons).translate(Vector3::new(T::zero(), half_h, T::zero()))
47}