#include <stdio.h>
#include <stdlib.h>
#include <math.h>
#include <time.h>
#include <ctlgeom.h>
/************************************************************************/
/* return a random number in [0,1]: */
static double mydrand(void)
{
double d = rand();
return (d / (double) RAND_MAX);
}
/* return a uniform random number in [a,b] */
static double myurand(double a, double b)
{
return ((b - a) * mydrand() + a);
}
#define K_PI 3.141592653589793238462643383279502884197
/* return a random unit vector, uniformly distributed over a sphere */
vector3 random_unit_vector3(void)
{
double z, t, r;
vector3 v;
z = 2*mydrand() - 1;
t = 2*K_PI*mydrand();
r = sqrt(1 - z*z);
v.x = r * cos(t);
v.y = r * sin(t);
v.z = z;
return v;
}
double find_edge(geometric_object o, vector3 dir, double max, double tol)
{
double min = 0;
if (!(point_in_fixed_objectp(vector3_scale(min, dir), o) &&
!point_in_fixed_objectp(vector3_scale(max, dir), o))) {
fprintf(stderr, "object out of bounds in find_edge");
exit(1);
}
do {
double d = (min + max) / 2;
if (point_in_fixed_objectp(vector3_scale(d, dir), o))
min = d;
else
max = d;
} while (max - min > tol);
return (min + max) / 2;
}
static vector3 make_vector3(double x, double y, double z)
{
vector3 v;
v.x = x; v.y = y; v.z = z;
return v;
}
/* return a random geometric object, centered at the origin, with
diameter roughly 1 */
geometric_object random_object(void)
{
material_type m = { 0 };
vector3 c = { 0, 0, 0 };
geometric_object o;
switch (rand() % 5) {
case 0:
o = make_sphere(m, c, myurand(0.5,1.5));
break;
case 1:
o = make_cylinder(m, c, myurand(0.5,1.5), myurand(0.5,1.5),
random_unit_vector3());
break;
case 2:
o = make_cone(m, c, myurand(0.5,1.5), myurand(0.5,1.5),
random_unit_vector3(), myurand(0.5,1.5));
break;
case 3:
o = make_block(m, c,
#if 1
random_unit_vector3(),
random_unit_vector3(),
random_unit_vector3(),
#else
make_vector3(1,0,0),
make_vector3(0,1,0),
make_vector3(0,0,1),
#endif
make_vector3(myurand(0.5,1.5),
myurand(0.5,1.5),
myurand(0.5,1.5)));
break;
case 4:
o = make_ellipsoid(m, c,
random_unit_vector3(),
random_unit_vector3(),
random_unit_vector3(),
make_vector3(myurand(0.5,1.5),
myurand(0.5,1.5),
myurand(0.5,1.5)));
break;
}
return o;
}
/************************************************************************/
static double simple_overlap(geom_box b, geometric_object o, double tol)
{
double d1,d2,d3, x1,x2,x3, olap0 = 0;
double itol = 1.0 / ((int) (1/tol + 0.5));
d1 = (b.high.x - b.low.x) * itol;
d2 = (b.high.y - b.low.y) * itol;
d3 = (b.high.z - b.low.z) * itol;
for (x1 = b.low.x + d1*0.5; x1 <= b.high.x; x1 += d1)
for (x2 = b.low.y + d2*0.5; x2 <= b.high.y; x2 += d2)
for (x3 = b.low.z + d3*0.5; x3 <= b.high.z; x3 += d3) {
vector3 v;
v.x = x1; v.y = x2; v.z = x3;
olap0 += d1*d2*d3 * point_in_fixed_objectp(v, o);
}
olap0 /= (b.high.x-b.low.x) * (b.high.y-b.low.y) * (b.high.z-b.low.z);
return olap0;
}
static void test_overlap(double tol)
{
geometric_object o = random_object();
vector3 dir = random_unit_vector3();
geom_box b;
double d, olap, olap0;
#if 1
geometry_lattice.basis1 = random_unit_vector3();
geometry_lattice.basis2 = random_unit_vector3();
geometry_lattice.basis3 = random_unit_vector3();
geom_fix_lattice();
geom_fix_object(o);
#endif
b.low = make_vector3(myurand(-1,0), myurand(-1,0), myurand(-1,0));
b.high = make_vector3(myurand(0,1), myurand(0,1), myurand(0,1));
d = find_edge(o, dir, 10, tol);
b.low = vector3_plus(b.low, vector3_scale(d, dir));
b.high = vector3_plus(b.high, vector3_scale(d, dir));
olap = box_overlap_with_object(b, o, tol, 100/tol);
olap0 = simple_overlap(b, o, tol);
if (fabs(olap0 - olap) > 2 * tol * fabs(olap)) {
fprintf(stderr, "Large error %e in overlap (%g vs. %g) for:\n"
" lattice = (%g,%g,%g), (%g,%g,%g), (%g,%g,%g)\n"
" box = (%g,%g,%g) - (%g,%g,%g)\n",
fabs(olap0 - olap) / fabs(olap),
olap, olap0,
geometry_lattice.basis1.x,
geometry_lattice.basis1.y,
geometry_lattice.basis1.z,
geometry_lattice.basis2.x,
geometry_lattice.basis2.y,
geometry_lattice.basis2.z,
geometry_lattice.basis3.x,
geometry_lattice.basis3.y,
geometry_lattice.basis3.z,
b.low.x, b.low.y, b.low.z,
b.high.x, b.high.y, b.high.z);
display_geometric_object_info(2, o);
#if 1
while (1) {
tol /= sqrt(2.0);
fprintf(stderr, "olap = %g, olap0 = %g (with tol = %e)\n",
box_overlap_with_object(b, o, tol, 100/tol),
simple_overlap(b, o, tol), tol);
}
#endif
exit(1);
}
else
printf("Got overlap %g vs. %g with tol = %e\n", olap,olap0,tol);
geometric_object_destroy(o);
}
/************************************************************************/
int main(void)
{
const int ntest = 100;
const double tol = 1e-2;
int i;
srand(time(NULL));
for (i = 0; i < ntest; ++i) test_overlap(tol);
return 0;
}
syntax highlighted by Code2HTML, v. 0.9.1