Skip to main content

rscad_csg_bsp/primitives/
cuboid.rs

1use crate::*;
2use nalgebra::{Point, Vector3};
3
4/// Create a cube (uniform cuboid) centered at the origin.
5///
6/// Use `translate` and `transform` methods to move it around.
7#[doc(alias = "box")]
8pub fn cube<T: Number>(size: T) -> Csg<T> {
9    cuboid(size, size, size)
10}
11
12/// Create a cuboid centered at the origin with the given dimensions.
13///
14/// Use `translate` and `transform` methods to move it around.
15#[doc(alias = "cube")]
16pub fn cuboid<T: Number>(x: T, y: T, z: T) -> Csg<T> {
17    let two = T::one() + T::one();
18    let hx = x / two;
19    let hy = y / two;
20    let hz = z / two;
21
22    //       7---------6
23    //      /|        /|
24    //     / |       / |
25    //    3---------2  |
26    //    |  4------|--5
27    //    | /       | /
28    //    |/        |/
29    //    0---------1
30    //
31    //  -X ← → +X
32    //  -Y ↓ ↑ +Y
33    //  -Z ● → +Z (out of screen)
34
35    let v = [
36        Point::from([-hx, -hy, -hz]), // 0: left  bottom back
37        Point::from([hx, -hy, -hz]),  // 1: right bottom back
38        Point::from([hx, hy, -hz]),   // 2: right top    back
39        Point::from([-hx, hy, -hz]),  // 3: left  top    back
40        Point::from([-hx, -hy, hz]),  // 4: left  bottom front
41        Point::from([hx, -hy, hz]),   // 5: right bottom front
42        Point::from([hx, hy, hz]),    // 6: right top    front
43        Point::from([-hx, hy, hz]),   // 7: left  top    front
44    ];
45
46    // Each face groups its vertices, normal, and plane distance together.
47    let faces: [([Point<T, 3>; 4], Vector3<T>, T); 6] = [
48        ([v[3], v[2], v[1], v[0]], -Vector3::z(), hz), // back   (-Z)
49        ([v[4], v[5], v[6], v[7]], Vector3::z(), hz),  // front  (+Z)
50        ([v[3], v[0], v[4], v[7]], -Vector3::x(), hx), // left   (-X)
51        ([v[1], v[2], v[6], v[5]], Vector3::x(), hx),  // right  (+X)
52        ([v[0], v[1], v[5], v[4]], -Vector3::y(), hy), // bottom (-Y)
53        ([v[2], v[3], v[7], v[6]], Vector3::y(), hy),  // top    (+Y)
54    ];
55
56    let polygons = faces.into_iter().flat_map(|(verts, normal, dist)| {
57        Polygon::from_points_and_plane(verts, Plane::new(normal, dist))
58    });
59
60    Csg::from_polygons(polygons).translate(Vector3::new(hx, hy, hz))
61}