11use crate :: aabb:: Aabb ;
22use crate :: mesh:: plane:: Plane ;
3+ use mixed_num:: { MixedAbs , MixedPi , MixedZero } ;
34use crate :: math_ndsp:: { Matrix3 , Matrix4 , Rotation3 , Translation3 , Vector3 , Scalar , eps} ;
45
56/// Boolean operations + transformations
67pub trait CSG : Sized + Clone {
8+ type Scalar : Scalar ;
9+
710 fn new ( ) -> Self ;
811 fn union ( & self , other : & Self ) -> Self ;
912 fn difference ( & self , other : & Self ) -> Self ;
1013 fn intersection ( & self , other : & Self ) -> Self ;
1114 fn xor ( & self , other : & Self ) -> Self ;
12- fn transform ( & self , matrix : & Matrix4 < Real > ) -> Self ;
15+ fn transform ( & self , matrix : & Matrix4 < Self :: Scalar > ) -> Self ;
1316 fn inverse ( & self ) -> Self ;
14- fn bounding_box ( & self ) -> Aabb < T > ;
17+ fn bounding_box ( & self ) -> Aabb < Self :: Scalar > ;
1518 fn invalidate_bounding_box ( & mut self ) ;
1619
1720 /// Returns a new Self translated by vector.
18- fn translate_vector ( & self , vector : Vector3 < Real > ) -> Self {
21+ fn translate_vector ( & self , vector : Vector3 < Self :: Scalar > ) -> Self {
1922 self . transform ( & Translation3 :: from ( vector) . to_homogeneous ( ) )
2023 }
2124
2225 /// Returns a new Self translated by x, y, and z.
23- fn translate ( & self , x : Real , y : Real , z : Real ) -> Self {
26+ fn translate ( & self , x : Self :: Scalar , y : Self :: Scalar , z : Self :: Scalar ) -> Self {
2427 self . translate_vector ( Vector3 :: new ( x, y, z) )
2528 }
2629
2730 /// Returns a new Self translated so that its bounding-box center is at the origin (0,0,0).
2831 fn center ( & self ) -> Self {
2932 let aabb = self . bounding_box ( ) ;
33+ let c2 = self :: Scalar :: mixed_from ( 0.5 ) ;
3034
3135 // Compute the AABB center
32- let center_x = ( aabb. mins . x + aabb. maxs . x ) * 0.5 ;
33- let center_y = ( aabb. mins . y + aabb. maxs . y ) * 0.5 ;
34- let center_z = ( aabb. mins . z + aabb. maxs . z ) * 0.5 ;
36+ let center_x = ( aabb. mins . x + aabb. maxs . x ) * c2 ;
37+ let center_y = ( aabb. mins . y + aabb. maxs . y ) * c2 ;
38+ let center_z = ( aabb. mins . z + aabb. maxs . z ) * c2 ;
3539
3640 // Translate so that the bounding-box center goes to the origin
3741 self . translate ( -center_x, -center_y, -center_z)
@@ -52,22 +56,23 @@ pub trait CSG: Sized + Clone {
5256 fn float ( & self ) -> Self {
5357 let aabb = self . bounding_box ( ) ;
5458 let min_z = aabb. mins . z ;
55- self . translate ( 0.0 , 0.0 , -min_z)
59+ self . translate ( Self :: Scalar :: mixed_zero ( ) , Self :: Scalar :: mixed_zero ( ) , -min_z)
5660 }
5761
5862 /// Rotates Self by x_degrees, y_degrees, z_degrees
59- fn rotate ( & self , x_deg : Real , y_deg : Real , z_deg : Real ) -> Self {
60- let rx = Rotation3 :: from_axis_angle ( & Vector3 :: x_axis ( ) , x_deg. to_radians ( ) ) ;
61- let ry = Rotation3 :: from_axis_angle ( & Vector3 :: y_axis ( ) , y_deg. to_radians ( ) ) ;
62- let rz = Rotation3 :: from_axis_angle ( & Vector3 :: z_axis ( ) , z_deg. to_radians ( ) ) ;
63+ fn rotate ( & self , x_deg : Self :: Scalar , y_deg : Self :: Scalar , z_deg : Self :: Scalar ) -> Self {
64+ let deg2rad = Self :: Scalar :: mixed_pi ( ) / Self :: Scalar :: mixed_from ( 180.0 ) ;
65+ let rx = Rotation3 :: from_axis_angle ( & Vector3 :: x_axis ( ) , x_deg * deg2rad) ;
66+ let ry = Rotation3 :: from_axis_angle ( & Vector3 :: y_axis ( ) , y_deg * deg2rad) ;
67+ let rz = Rotation3 :: from_axis_angle ( & Vector3 :: z_axis ( ) , z_deg * deg2rad) ;
6368
6469 // Compose them in the desired order
6570 let rot = rz * ry * rx;
6671 self . transform ( & rot. to_homogeneous ( ) )
6772 }
6873
6974 /// Scales Self by scale_x, scale_y, scale_z
70- fn scale ( & self , sx : Real , sy : Real , sz : Real ) -> Self {
75+ fn scale ( & self , sx : Self :: Scalar , sy : Self :: Scalar , sz : Self :: Scalar ) -> Self {
7176 let mat4 = Matrix4 :: scaling ( sx, sy, sz) ;
7277 self . transform ( & mat4)
7378 }
@@ -116,10 +121,10 @@ pub trait CSG: Sized + Clone {
116121 /// the orientation of polygons, affecting inside/outside semantics in CSG.
117122 ///
118123 /// Returns a new Self whose geometry is mirrored accordingly.
119- fn mirror ( & self , plane : Plane < T > ) -> Self {
124+ fn mirror ( & self , plane : Plane < Self :: Scalar > ) -> Self {
120125 // Normal might not be unit, so compute its length:
121126 let len = plane. normal ( ) . norm ( ) ;
122- if len. abs ( ) < eps :: < T > ( ) {
127+ if len. mixed_abs ( ) <= eps :: < Self :: Scalar > ( ) {
123128 // Degenerate plane? Just return clone (no transform)
124129 return self . clone ( ) ;
125130 }
@@ -139,7 +144,7 @@ pub trait CSG: Sized + Clone {
139144 //let mut reflect_4 = Matrix4::identity();
140145 //let reflect_3 = Matrix3::identity() - 2.0 * n * n.transpose();
141146 let reflect_3 = Matrix3 :: reflection_about_unit_normal ( n) ;
142- let r4 = Matrix4 :: from_matrix3_and_translation ( reflect_3, Vector3 :: zeros ( ) ) ;
147+ let r4 = Matrix4 :: from_matrix3_and_translation ( reflect_3, Vector3 :: mixed_zeroes ( ) ) ;
143148 //reflect_4.fixed_view_mut::<3, 3>(0, 0).copy_from(&reflect_3);
144149
145150 // Translate back
@@ -158,23 +163,25 @@ pub trait CSG: Sized + Clone {
158163 fn distribute_arc (
159164 & self ,
160165 count : usize ,
161- radius : Real ,
162- start_angle_deg : Real ,
163- end_angle_deg : Real ,
166+ radius : Self :: Scalar ,
167+ start_angle_deg : Self :: Scalar ,
168+ end_angle_deg : Self :: Scalar ,
164169 ) -> Self {
165170 if count < 1 {
166171 return self . clone ( ) ;
167172 }
168- let start_rad = start_angle_deg. to_radians ( ) ;
169- let end_rad = end_angle_deg. to_radians ( ) ;
173+ let deg2rad = Self :: Scalar :: mixed_pi ( ) / Self :: Scalar :: mixed_from ( 180.0 ) ;
174+ let start_rad = start_angle_deg * deg2rad;
175+ let end_rad = end_angle_deg * deg2rad;
170176 let sweep = end_rad - start_rad;
171177
172178 ( 0 ..count)
173179 . map ( |i| {
174180 let t = if count == 1 {
175- 0.5
181+ Self :: Scalar :: mixed_from ( 0.5 )
176182 } else {
177- i as Real / ( ( count - 1 ) as Real )
183+ Self :: Scalar :: mixed_from ( i)
184+ / Self :: Scalar :: mixed_from ( ( count - 1 ) )
178185 } ;
179186
180187 let angle = start_rad + t * sweep;
@@ -183,7 +190,7 @@ pub trait CSG: Sized + Clone {
183190 . to_homogeneous ( ) ;
184191
185192 // translate out to radius in x
186- let trans = Translation3 :: new ( radius, 0.0 , 0.0 ) . to_homogeneous ( ) ;
193+ let trans = Translation3 :: new ( radius, Self :: Scalar :: mixed_zero ( ) , Self :: Scalar :: mixed_zero ( ) ) . to_homogeneous ( ) ;
187194 let mat = rot * trans;
188195 self . transform ( & mat)
189196 } )
@@ -198,8 +205,8 @@ pub trait CSG: Sized + Clone {
198205 fn distribute_linear (
199206 & self ,
200207 count : usize ,
201- dir : Vector3 < Real > ,
202- spacing : Real ,
208+ dir : Vector3 < Self :: Scalar > ,
209+ spacing : Self :: Scalar ,
203210 ) -> Self {
204211 if count < 1 {
205212 return self . clone ( ) ;
@@ -208,8 +215,8 @@ pub trait CSG: Sized + Clone {
208215
209216 ( 0 ..count)
210217 . map ( |i| {
211- let offset = step * ( i as Real ) ;
212- let trans = Translation3 :: from ( offset) . to_homogeneous ( ) ;
218+ let offset = Self :: Scalar :: mixed_from ( i ) ;
219+ let trans = Translation3 :: from ( offset * step ) . to_homogeneous ( ) ;
213220 self . transform ( & trans)
214221 } )
215222 . reduce ( |acc, csg| acc. union ( & csg) )
@@ -218,17 +225,19 @@ pub trait CSG: Sized + Clone {
218225
219226 /// Distribute Self in a grid of `rows x cols`, with spacing dx, dy in XY plane.
220227 /// top-left or bottom-left depends on your usage of row/col iteration.
221- fn distribute_grid ( & self , rows : usize , cols : usize , dx : Real , dy : Real ) -> Self {
228+ fn distribute_grid ( & self , rows : usize , cols : usize , dx : Self :: Scalar , dy : Self :: Scalar ) -> Self {
222229 if rows < 1 || cols < 1 {
223230 return self . clone ( ) ;
224231 }
225- let step_x = Vector3 :: new ( dx, 0.0 , 0.0 ) ;
226- let step_y = Vector3 :: new ( 0.0 , dy, 0.0 ) ;
232+ let step_x = Vector3 :: new ( dx, Self :: Scalar :: mixed_zero ( ) , Self :: Scalar :: mixed_zero ( ) ) ;
233+ let step_y = Vector3 :: new ( Self :: Scalar :: mixed_zero ( ) , dy, Self :: Scalar :: mixed_zero ( ) ) ;
227234
228235 ( 0 ..rows)
229236 . flat_map ( |r| {
230237 ( 0 ..cols) . map ( move |c| {
231- let offset = step_x * ( c as Real ) + step_y * ( r as Real ) ;
238+ let rx = Self :: Scalar :: mixed_from ( c) ;
239+ let ry = Self :: Scalar :: mixed_from ( r) ;
240+ let offset = step_x * rx + step_y * ry;
232241 let trans = Translation3 :: from ( offset) . to_homogeneous ( ) ;
233242 self . transform ( & trans)
234243 } )
0 commit comments