3333
3434#define K_PI 3.141592653589793238462643383279502884197
3535
36- #define NUMPTS 10000
37- #define NUMLINES 1000
38-
39- #define LX 0.5
40- #define LY 1.0
41- #define LZ 1.5
42-
4336// routine from geom.c that rotates the coordinate of a point
4437// from the prism coordinate system to the cartesian coordinate system
4538vector3 prism_coordinate_p2c (prism * prsm , vector3 vp );
@@ -63,22 +56,69 @@ static double drand()
6356/************************************************************************/
6457/* random point uniformly distributed over a parallelepiped */
6558/************************************************************************/
66- vector3 random_point (vector3 min_corner , vector3 max_corner )
67- { return make_vector3 ( urand (min_corner .x , max_corner .x ),
59+ vector3 random_point_in_box (vector3 min_corner , vector3 max_corner )
60+ {
61+ return make_vector3 ( urand (min_corner .x , max_corner .x ),
6862 urand (min_corner .y , max_corner .y ),
6963 urand (min_corner .z , max_corner .z )
7064 );
7165}
7266
7367/************************************************************************/
74- /* random unit vector uniformly distributed over a sphere */
68+ /* random point uniformly distributed over a planar polygon */
69+ /* (all z coordinates are 0) */
70+ /************************************************************************/
71+ vector3 random_point_in_polygon (vector3 * vertices , int num_vertices )
72+ {
73+ // randomly choose a vertex and generate random point within the triangle
74+ // formed by that vertex, the next vertex, and the centroid
75+ int which_vertex = rand () % num_vertices ;
76+ vector3 v0 = {0 ,0 ,0 };
77+ vector3 v1 = vertices [which_vertex ];
78+ vector3 v2 = vertices [(which_vertex + 1 )%num_vertices ];
79+ double xi = urand (0.0 ,1.0 ), eta = urand (0.0 ,1.0 - xi );
80+ return vector3_plus ( vector3_scale (xi , vector3_minus (v1 ,v0 )),
81+ vector3_scale (eta , vector3_minus (v2 ,v0 ))
82+ );
83+ }
84+
85+
86+ /************************************************************************/
87+ /* random point uniformly distributed over the surface of a prism */
88+ /************************************************************************/
89+ vector3 random_point_on_prism (geometric_object o )
90+ {
91+ prism * prsm = o .subclass .prism_data ;
92+ vector3 * vertices = prsm -> vertices .items ;
93+ int num_vertices = prsm -> vertices .num_items ;
94+ double height = prsm -> height ;
95+
96+ // choose a face
97+ int num_faces = num_vertices + 2 ;
98+ int which_face = rand () % num_faces ;
99+ if ( which_face < num_vertices ) // side face
100+ { vector3 min_corner = vertices [which_face ];
101+ vector3 max_corner = vertices [ (which_face + 1 )%num_vertices ];
102+ max_corner .z = height ;
103+ return random_point_in_box ( prism_coordinate_p2c (prsm , min_corner ),
104+ prism_coordinate_p2c (prsm , max_corner ) );
105+ }
106+ else // floor or ceiling
107+ {
108+ vector3 p = random_point_in_polygon (vertices , num_vertices );
109+ if (which_face == num_faces - 1 ) p .z = height ;
110+ return prism_coordinate_p2c (prsm , p );
111+ }
112+ }
113+
114+ /************************************************************************/
115+ /* random unit vector with direction uniformly distributed over unit sphere*/
75116/************************************************************************/
76- vector3 random_unit_vector3 (void )
117+ vector3 random_unit_vector3 ()
77118{
78- double z = urand (-1.0 ,1.0 );
79- double rho = sqrt (1 - z * z );
80- double phi = urand (0.0 , 2.0 * K_PI );
81- return make_vector3 ( rho * cos (phi ), rho * sin (phi ), z );
119+ double cos_theta = urand (0.0 ,1.0 ), sin_theta = sqrt (1.0 - cos_theta * cos_theta );
120+ double phi = urand (0.0 ,2.0 * K_PI );
121+ return make_vector3 (sin_theta * cos (phi ), sin_theta * sin (phi ), cos_theta );
82122}
83123
84124/***************************************************************/
@@ -169,7 +209,7 @@ int test_point_inclusion(geometric_object the_block, geometric_object the_prism,
169209 int n ;
170210 for (n = 0 ; n < num_tests ; n ++ )
171211 {
172- vector3 p = random_point (min_corner , max_corner );
212+ vector3 p = random_point_in_box (min_corner , max_corner );
173213 boolean in_block = point_in_objectp (p ,the_block );
174214 boolean in_prism = point_in_objectp (p ,the_prism );
175215 if (in_block != in_prism )
@@ -185,6 +225,7 @@ int test_point_inclusion(geometric_object the_block, geometric_object the_prism,
185225/************************************************************************/
186226/* second unit test: check calculation of normals to objects */
187227/************************************************************************/
228+ #define PFACE 0.1
188229int test_normal_to_object (geometric_object the_block , geometric_object the_prism ,
189230 int num_tests , int write_log )
190231{
@@ -194,13 +235,18 @@ int test_normal_to_object(geometric_object the_block, geometric_object the_prism
194235 FILE * f = write_log ? fopen ("/tmp/test-prism.normals" ,"w" ) : 0 ;
195236
196237 int num_failed = 0 ;
197- int n ;
198238 double tolerance = 1.0e-6 ;
239+
240+ int n ;
199241 for (n = 0 ; n < num_tests ; n ++ )
200242 {
201- // randomly generated base point within enlarged bounding box
202- vector3 p = random_point (min_corner , max_corner );
203-
243+ // with probability PFACE, generate random base point lying on one
244+ // of the 6 faces of the prism.
245+ // with probability 1-PFACE, generate random base point lying in the
246+ // extended volume (2x volume of block)
247+ vector3 p = ( urand (0.0 ,1.0 ) < PFACE ) ? random_point_on_prism (the_prism )
248+ : random_point_in_box (min_corner , max_corner );
249+
204250 vector3 nhat_block = standardize (normal_to_object (p , the_block ));
205251 vector3 nhat_prism = standardize (normal_to_object (p , the_prism ));
206252 if (!vector3_nearly_equal (nhat_block , nhat_prism , tolerance ))
@@ -234,7 +280,7 @@ int test_line_segment_intersection(geometric_object the_block, geometric_object
234280 for (n = 0 ; n < num_tests ; n ++ )
235281 {
236282 // randomly generated base point within enlarged bounding box
237- vector3 p = random_point (min_corner , max_corner );
283+ vector3 p = random_point_in_box (min_corner , max_corner );
238284 vector3 d = random_unit_vector3 ();
239285 double a = urand (0.0 ,1.0 );
240286 double b = urand (0.0 ,1.0 );
@@ -258,6 +304,13 @@ int test_line_segment_intersection(geometric_object the_block, geometric_object
258304/* block and as a prism) and verify that geometric primitives */
259305/* give identical results */
260306/***************************************************************/
307+ #define NUMPTS 10000
308+ #define NUMLINES 1000
309+
310+ #define LX 0.5
311+ #define LY 1.0
312+ #define LZ 1.5
313+
261314int run_unit_tests ()
262315{
263316 void * m = NULL ;
@@ -266,16 +319,18 @@ int run_unit_tests()
266319 vector3 yhat = make_vector3 (0 ,1 ,0 );
267320 vector3 zhat = make_vector3 (0 ,0 ,1 );
268321 vector3 size = make_vector3 (LX ,LY ,LZ );
269- geometric_object the_block = make_block (m , c , xhat , yhat , zhat , size );
270322
271323 vector3 v [4 ];
272324 v [0 ].x = -0.5 * LX ; v [0 ].y = -0.5 * LY ; v [0 ].z = -0.5 * LZ ;
273325 v [1 ].x = +0.5 * LX ; v [1 ].y = -0.5 * LY ; v [1 ].z = -0.5 * LZ ;
274326 v [2 ].x = +0.5 * LX ; v [2 ].y = +0.5 * LY ; v [2 ].z = -0.5 * LZ ;
275327 v [3 ].x = -0.5 * LX ; v [3 ].y = +0.5 * LY ; v [3 ].z = -0.5 * LZ ;
328+
329+ geometric_object the_block = make_block (m , c , xhat , yhat , zhat , size );
276330 geometric_object the_prism = make_prism (m , v , 4 , LZ , zhat );
277331
278- int write_log = 0 ;
332+ char * s = getenv ("LIBCTL_TEST_PRISM_LOG" );
333+ int write_log = (s && s [0 ]== '1' ) ? 1 : 0 ;
279334
280335 if (write_log )
281336 prism2gnuplot (the_prism .subclass .prism_data , "/tmp/test-prism.prism" );
0 commit comments