rust_3d/
box_unaligned_3d.rs1use crate::*;
26
27#[derive(Clone)]
31pub struct BoxUnaligned3D {
32 pub center: Point3D,
34 pub y_dir: Norm3D,
35 pub z_dir: Norm3D,
36 pub size: [Positive; 3],
37}
38
39impl BoxUnaligned3D {
42 pub fn new_from_bb(bb: &BoundingBox3D) -> Self {
43 let center = Point3D::new_from(&bb.center_bb());
44 let y_dir = Norm3D::norm_y();
45 let z_dir = Norm3D::norm_z();
46 let size = [bb.size_x(), bb.size_y(), bb.size_z()];
47
48 Self {
49 center,
50 y_dir,
51 z_dir,
52 size,
53 }
54 }
55 pub fn new_from_z_rotation<P>(center: &P, size: [Positive; 3], rotation: f64) -> Self
56 where
57 P: Is3D,
58 {
59 let mut y_dir = Point3D::new(0.0, 1.0, 0.0);
60 let z_dir = Norm3D::norm_z();
61
62 y_dir = rot2d(&y_dir, rotation);
63 Self {
64 center: Point3D::new_from(center),
65 size,
66 y_dir: Norm3D::new(y_dir).unwrap(), z_dir,
68 }
69 }
70 fn d_x(&self) -> Point3D {
71 let d = self.size[0].get();
72 Point3D::new_from(&self.x_dir()) * d
73 }
74 fn d_y(&self) -> Point3D {
75 let d = self.size[1].get();
76 Point3D::new_from(&self.y_dir) * d
77 }
78 fn d_z(&self) -> Point3D {
79 let d = self.size[2].get();
80 Point3D::new_from(&self.z_dir) * d
81 }
82 pub fn x_dir(&self) -> Norm3D {
83 Norm3D::new(cross(&self.z_dir, &Point3D::new_from(&self.y_dir))).unwrap_or(Norm3D::norm_z())
84 }
85}
86
87impl IsMovable3D for BoxUnaligned3D {
90 fn move_by(&mut self, x: f64, y: f64, z: f64) {
91 self.center.move_by(x, y, z);
92 }
93}
94
95impl IsSATObject for BoxUnaligned3D {
98 fn for_each_point<F>(&self, f: &mut F)
100 where
101 F: FnMut(&Point3D),
102 {
103 let c = &self.center;
104 let dx = &Point3D::new_from(&self.d_x());
105 let dy = &Point3D::new_from(&self.d_y());
106 let dz = &Point3D::new_from(&self.d_z());
107
108 f(&(c - dx - (dy - dz)));
109 f(&(c - dx - (dy + dz)));
110 f(&(c - dx + (dy - dz)));
111 f(&(c - dx + (dy + dz)));
112 f(&(c + dx - (dy - dz)));
113 f(&(c + dx - (dy + dz)));
114 f(&(c + dx + (dy - dz)));
115 f(&(c + dx + (dy + dz)));
116 }
117
118 fn for_each_axis<F>(&self, f: &mut F)
119 where
120 F: FnMut(&Norm3D),
121 {
122 f(&self.x_dir());
123 f(&self.y_dir);
124 f(&self.z_dir);
125 }
126}
127
128impl HasBoundingBox3D for BoxUnaligned3D {
131 fn bounding_box(&self) -> BoundingBox3D {
132 let mut max_size = self.size[0];
133 if self.size[1] > max_size {
134 max_size = self.size[1]
135 }
136 if self.size[2] > max_size {
137 max_size = self.size[2]
138 }
139
140 BoundingBox3D::new(
141 &Point3D::new(
142 self.center.x() - 0.5 * max_size.get(),
143 self.center.y() - 0.5 * max_size.get(),
144 self.center.z() - 0.5 * max_size.get(),
145 ),
146 &Point3D::new(
147 self.center.x() + 0.5 * max_size.get(),
148 self.center.y() + 0.5 * max_size.get(),
149 self.center.z() + 0.5 * max_size.get(),
150 ),
151 )
152 .unwrap() }
154}
155
156impl HasBoundingBox3DMaybe for BoxUnaligned3D {
157 fn bounding_box_maybe(&self) -> Result<BoundingBox3D> {
158 Ok(self.bounding_box())
159 }
160}
161
162fn rot2d<P>(p: &P, phi: f64) -> P
165where
166 P: IsBuildable3D,
167{
168 let s = (-phi).sin();
169 let c = (-phi).cos();
170
171 P::new(p.x() * c - p.y() * s, p.x() * s + p.y() * c, p.z())
172}