1+ use matrixcompare:: assert_scalar_eq;
12use fenris_geometry:: AxisAlignedBoundingBox ;
23use nalgebra:: { DefaultAllocator , DimName , OPoint , point, U2 } ;
34use nalgebra:: allocator:: Allocator ;
5+ use proptest:: prelude:: * ;
46use fenris:: allocators:: DimAllocator ;
7+ use fenris_geometry:: proptest:: { aabb2, aabb3, point2, point3} ;
8+ use nalgebra:: distance_squared;
59
610#[ test]
711fn aabb_intersects_2d ( ) {
@@ -110,6 +114,85 @@ fn test_aabb_corners_iter() {
110114 ] . map ( OPoint :: from) ;
111115 assert_unordered_eq ! ( corners( & aabb) , expected) ;
112116 }
117+ }
118+
119+ #[ test]
120+ fn test_furthest_point_2d ( ) {
121+ let aabb = AxisAlignedBoundingBox :: new ( point ! [ 1.0 , 1.0 ] , point ! [ 2.0 , 3.0 ] ) ;
122+
123+ {
124+ let p = point ! [ 0.0 , 0.0 ] ;
125+ let q = aabb. furthest_point_to ( & p) ;
126+ assert_eq ! ( q, point![ 2.0 , 3.0 ] ) ;
127+ // We check all the convenience method results here just to have a unit test that does
128+ // this, but the consistency is separately tested by proptests, which is why
129+ // we don't do this for every test
130+ let dist2: f64 = distance_squared ( & q, & p) ;
131+ assert_scalar_eq ! ( dist2, 13.0 ) ;
132+ assert_scalar_eq ! ( dist2, aabb. max_dist2_to( & p) ) ;
133+ assert_scalar_eq ! ( aabb. max_dist_to( & p) , f64 :: sqrt( 13.0 ) ) ;
134+ }
135+
136+ {
137+ let p = point ! [ 1.5 , 2.0 ] ;
138+ let q = aabb. furthest_point_to ( & p) ;
139+ // The exact point is not unique: any corner will be applicable
140+ assert_scalar_eq ! ( distance_squared( & q, & p) , 1.25 ) ;
141+ }
142+ }
143+
144+ proptest ! {
113145
146+ #[ test]
147+ fn aabb_max_dists_agree_with_furthest_point_2d( point in point2( ) , aabb in aabb2( ) ) {
148+ let q = aabb. furthest_point_to( & point) ;
149+ let dist2 = distance_squared( & q, & point) ;
150+ prop_assert_eq!( aabb. max_dist2_to( & point) , dist2) ;
151+ prop_assert_eq!( aabb. max_dist_to( & point) , dist2. sqrt( ) ) ;
152+ }
153+
154+ #[ test]
155+ fn aabb_max_dists_agree_with_furthest_point_3d( point in point3( ) , aabb in aabb3( ) ) {
156+ let q = aabb. furthest_point_to( & point) ;
157+ let dist2 = distance_squared( & q, & point) ;
158+ prop_assert_eq!( aabb. max_dist2_to( & point) , dist2) ;
159+ prop_assert_eq!( aabb. max_dist_to( & point) , dist2. sqrt( ) ) ;
160+ }
161+
162+ #[ test]
163+ fn aabb_furthest_point_2d( p in point2( ) , aabb in aabb2( ) ) {
164+ // The furthest point in the AABB is *always* a corner, so we must satisfy
165+ // dist(p, q) <= dist(p, c)
166+ // for all corners c and furthest point q
167+ let q = aabb. furthest_point_to( & p) ;
168+ let further_away_than_all_corners = aabb. corners_iter( )
169+ . all( |corner| distance_squared( & p, & q) >= distance_squared( & p, & corner) ) ;
170+ prop_assert!( further_away_than_all_corners) ;
171+
172+ // The result should be exactly one of the corners, and since there are no floating
173+ // point operations applied to the result (all numbers are just copied),
174+ // there should also be no round-off error in the result, so we should
175+ // be safe to check if the point is contained in the AABB, despite the fact that it
176+ // resides exactly on the boundary!
177+ prop_assert!( aabb. contains_point( & q) ) ;
178+ }
179+
180+ #[ test]
181+ fn aabb_furthest_point_3d( p in point3( ) , aabb in aabb3( ) ) {
182+ // The furthest point in the AABB is *always* a corner, so we must satisfy
183+ // dist(p, q) <= dist(p, c)
184+ // for all corners c and furthest point q
185+ let q = aabb. furthest_point_to( & p) ;
186+ let further_away_than_all_corners = aabb. corners_iter( )
187+ . all( |corner| distance_squared( & p, & q) >= distance_squared( & p, & corner) ) ;
188+ prop_assert!( further_away_than_all_corners) ;
189+
190+ // The result should be exactly one of the corners, and since there are no floating
191+ // point operations applied to the result (all numbers are just copied),
192+ // there should also be no round-off error in the result, so we should
193+ // be safe to check if the point is contained in the AABB, despite the fact that it
194+ // resides exactly on the boundary!
195+ prop_assert!( aabb. contains_point( & q) ) ;
196+ }
114197
115198}
0 commit comments