@@ -28,22 +28,25 @@ impl<const D: usize> BoundingBox<D> {
2828 ///
2929 /// This is the smallest rectangle (rectangular cuboid in 3D) that both
3030 /// contains all given points and is aligned with the axises.
31- pub fn from_points < P > ( points : P ) -> Self
31+ ///
32+ /// Returns `None` iff the given iterator is empty.
33+ pub fn from_points < P > ( points : P ) -> Option < Self >
3234 where
3335 P : IntoParallelIterator < Item = PointND < D > > ,
3436 P :: Iter : IndexedParallelIterator ,
3537 {
3638 let points = points. into_par_iter ( ) ;
37- assert ! ( 1 < points. len( ) ) ;
38-
39- let ( min, max) = points
39+ if points. len ( ) == 0 {
40+ return None ;
41+ }
42+ let ( p_min, p_max) = points
4043 . fold_with (
4144 (
4245 PointND :: < D > :: from_element ( std:: f64:: MAX ) ,
4346 PointND :: < D > :: from_element ( std:: f64:: MIN ) ,
4447 ) ,
4548 |( mut mins, mut maxs) , vals| {
46- for ( ( min, max) , val) in mins. iter_mut ( ) . zip ( maxs. iter_mut ( ) ) . zip ( vals. iter ( ) ) {
49+ for ( ( min, max) , val) in mins. iter_mut ( ) . zip ( maxs. iter_mut ( ) ) . zip ( & vals) {
4750 if * val < * min {
4851 * min = * val;
4952 }
@@ -59,23 +62,19 @@ impl<const D: usize> BoundingBox<D> {
5962 PointND :: < D > :: from_iterator (
6063 mins_left
6164 . into_iter ( )
62- . zip ( mins_right. into_iter ( ) )
65+ . zip ( & mins_right)
6366 . map ( |( left, right) | left. min ( * right) ) ,
6467 ) ,
6568 PointND :: < D > :: from_iterator (
6669 maxs_left
6770 . into_iter ( )
68- . zip ( maxs_right. into_iter ( ) )
71+ . zip ( & maxs_right)
6972 . map ( |( left, right) | left. max ( * right) ) ,
7073 ) ,
7174 )
7275 } )
73- . unwrap ( ) ;
74-
75- Self {
76- p_min : min,
77- p_max : max,
78- }
76+ . unwrap ( ) ; // fold_with yields at least one element.
77+ Some ( Self { p_min, p_max } )
7978 }
8079
8180 fn center ( & self ) -> PointND < D > {
@@ -213,7 +212,7 @@ impl<const D: usize> OrientedBoundingBox<D> {
213212 /// The arbitrarily-oriented *minimum* bounding box.
214213 ///
215214 /// The smallest box that contains all given points.
216- pub fn from_points ( points : & [ PointND < D > ] ) -> Self
215+ pub fn from_points ( points : & [ PointND < D > ] ) -> Option < Self >
217216 where
218217 Const < D > : DimSub < Const < 1 > > ,
219218 DefaultAllocator : Allocator < f64 , Const < D > , Const < D > , Buffer = ArrayStorage < f64 , D , D > >
@@ -225,13 +224,13 @@ impl<const D: usize> OrientedBoundingBox<D> {
225224 let base_change = householder_reflection ( & vec) ;
226225 let obb_to_aabb = base_change. try_inverse ( ) . unwrap ( ) ;
227226 let mapped = points. par_iter ( ) . map ( |p| obb_to_aabb * p) ;
228- let aabb = BoundingBox :: from_points ( mapped) ;
227+ let aabb = BoundingBox :: from_points ( mapped) ? ;
229228
230- Self {
229+ Some ( Self {
231230 aabb,
232231 aabb_to_obb : base_change,
233232 obb_to_aabb,
234- }
233+ } )
235234 }
236235
237236 /// Constructs a new Mbr that is a sub-Mbr of the current one.
@@ -365,23 +364,16 @@ mod tests {
365364 Point2D :: from ( [ 4. , 5. ] ) ,
366365 ] ;
367366
368- let aabb = BoundingBox :: from_points ( points) ;
367+ let aabb = BoundingBox :: from_points ( points) . unwrap ( ) ;
369368
370369 assert_ulps_eq ! ( aabb. p_min, Point2D :: from( [ 0. , 0. ] ) ) ;
371370 assert_ulps_eq ! ( aabb. p_max, Point2D :: from( [ 5. , 5. ] ) ) ;
372371 }
373372
374373 #[ test]
375374 #[ should_panic]
376- fn test_aabb2d_invalid_input_1 ( ) {
377- let _aabb = BoundingBox :: < 2 > :: from_points ( [ ] ) ;
378- }
379-
380- #[ test]
381- #[ should_panic]
382- fn test_aabb2d_invalid_input_2 ( ) {
383- let points = [ Point2D :: from ( [ 5. , -9.2 ] ) ] ;
384- let _aabb = BoundingBox :: from_points ( points) ;
375+ fn test_aabb2d_invalid_input ( ) {
376+ BoundingBox :: < 2 > :: from_points ( [ ] ) . unwrap ( ) ;
385377 }
386378
387379 #[ test]
@@ -422,29 +414,29 @@ mod tests {
422414
423415 #[ test]
424416 fn test_obb_center ( ) {
425- let points = vec ! [
417+ let points = [
426418 Point2D :: from ( [ 0. , 1. ] ) ,
427419 Point2D :: from ( [ 1. , 0. ] ) ,
428420 Point2D :: from ( [ 5. , 6. ] ) ,
429421 Point2D :: from ( [ 6. , 5. ] ) ,
430422 ] ;
431423
432- let obb = OrientedBoundingBox :: from_points ( & points) ;
424+ let obb = OrientedBoundingBox :: from_points ( & points) . unwrap ( ) ;
433425
434426 let center = obb. center ( ) ;
435427 assert_ulps_eq ! ( center, Point2D :: from( [ 3. , 3. ] ) )
436428 }
437429
438430 #[ test]
439431 fn test_obb_contains ( ) {
440- let points = vec ! [
432+ let points = [
441433 Point2D :: from ( [ 0. , 1. ] ) ,
442434 Point2D :: from ( [ 1. , 0. ] ) ,
443435 Point2D :: from ( [ 5. , 6. ] ) ,
444436 Point2D :: from ( [ 6. , 5. ] ) ,
445437 ] ;
446438
447- let obb = OrientedBoundingBox :: from_points ( & points) ;
439+ let obb = OrientedBoundingBox :: from_points ( & points) . unwrap ( ) ;
448440
449441 assert ! ( !obb. contains( & Point2D :: from( [ 0. , 0. ] ) ) ) ;
450442 assert ! ( obb. contains( & obb. center( ) ) ) ;
@@ -458,14 +450,14 @@ mod tests {
458450
459451 #[ test]
460452 fn test_obb_quadrant ( ) {
461- let points = vec ! [
453+ let points = [
462454 Point2D :: from ( [ 0. , 1. ] ) ,
463455 Point2D :: from ( [ 1. , 0. ] ) ,
464456 Point2D :: from ( [ 5. , 6. ] ) ,
465457 Point2D :: from ( [ 6. , 5. ] ) ,
466458 ] ;
467459
468- let obb = OrientedBoundingBox :: from_points ( & points) ;
460+ let obb = OrientedBoundingBox :: from_points ( & points) . unwrap ( ) ;
469461
470462 let none = obb. region ( & Point2D :: from ( [ 0. , 0. ] ) ) ;
471463 let q1 = obb. region ( & Point2D :: from ( [ 1.2 , 1.2 ] ) ) ;
@@ -524,7 +516,7 @@ mod tests {
524516 Point3D :: from ( [ 4. , 5. , 3. ] ) ,
525517 ] ;
526518
527- let aabb = BoundingBox :: from_points ( points) ;
519+ let aabb = BoundingBox :: from_points ( points) . unwrap ( ) ;
528520
529521 assert_ulps_eq ! ( aabb. p_min, Point3D :: from( [ 0. , 0. , -2. ] ) ) ;
530522 assert_ulps_eq ! ( aabb. p_max, Point3D :: from( [ 5. , 5. , 5. ] ) ) ;
@@ -551,7 +543,7 @@ mod tests {
551543
552544 #[ test]
553545 fn test_obb_octant ( ) {
554- let points = vec ! [
546+ let points = [
555547 Point3D :: from ( [ 0. , 1. , 0. ] ) ,
556548 Point3D :: from ( [ 1. , 0. , 0. ] ) ,
557549 Point3D :: from ( [ 5. , 6. , 0. ] ) ,
@@ -562,8 +554,7 @@ mod tests {
562554 Point3D :: from ( [ 6. , 5. , 1. ] ) ,
563555 ] ;
564556
565- let obb = OrientedBoundingBox :: from_points ( & points) ;
566- eprintln ! ( "obb = {:#?}" , obb) ;
557+ let obb = OrientedBoundingBox :: from_points ( & points) . unwrap ( ) ;
567558
568559 let none = obb. region ( & Point3D :: from ( [ 0. , 0. , 0. ] ) ) ;
569560 let octants = vec ! [
0 commit comments