Skip to content

Commit fead47c

Browse files
authored
geometric_object_volume (#45)
* geom_object_volume function * more tests * some bug fixes * more fixes * don't use geom_object_volume in 1d and 2d cases
1 parent 683b5d1 commit fead47c

3 files changed

Lines changed: 132 additions & 45 deletions

File tree

utils/ctlgeom.h

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -68,6 +68,7 @@ extern void geom_fix_lattice(void);
6868
extern void geom_fix_lattice0(LATTICE *L);
6969
extern void geom_cartesian_lattice(void);
7070
extern void geom_cartesian_lattice0(LATTICE *L);
71+
extern double geom_object_volume(GEOMETRIC_OBJECT o);
7172
extern boolean point_in_objectp(vector3 p, GEOMETRIC_OBJECT o);
7273
extern boolean point_in_periodic_objectp(vector3 p, GEOMETRIC_OBJECT o);
7374
extern boolean point_in_fixed_objectp(vector3 p, GEOMETRIC_OBJECT o);

utils/geom.c

Lines changed: 47 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1016,6 +1016,47 @@ matrix3x3 CTLIO square_basis(matrix3x3 basis, vector3 size)
10161016
return matrix3x3_mult(matrix3x3_inverse(basis), square);
10171017
}
10181018

1019+
/**************************************************************************/
1020+
1021+
/* compute the 3d volume enclosed by a geometric object o. */
1022+
1023+
double geom_object_volume(GEOMETRIC_OBJECT o)
1024+
{
1025+
switch (o.which_subclass) {
1026+
case GEOM SPHERE: {
1027+
number radius = o.subclass.sphere_data->radius;
1028+
return (1.333333333333333333 * K_PI) * radius*radius*radius;
1029+
}
1030+
case GEOM CYLINDER: {
1031+
number height = o.subclass.cylinder_data->height;
1032+
number radius = o.subclass.cylinder_data->radius;
1033+
number radius2 = o.subclass.cylinder_data->which_subclass == CYL CONE ? o.subclass.cylinder_data->subclass.cone_data->radius2 : radius;
1034+
double vol = height * (K_PI/3) * (radius*radius + radius*radius2 + radius2*radius2);
1035+
if (o.subclass.cylinder_data->which_subclass == CYL WEDGE)
1036+
return vol * fabs(o.subclass.cylinder_data->subclass.wedge_data->wedge_angle) / (2*K_PI);
1037+
else
1038+
return vol;
1039+
}
1040+
case GEOM BLOCK: {
1041+
vector3 size = o.subclass.block_data->size;
1042+
double vol = size.x * size.y * size.z * fabs(matrix3x3_determinant(geometry_lattice.basis) / matrix3x3_determinant(o.subclass.block_data->projection_matrix));
1043+
return o.subclass.block_data->which_subclass == BLK BLOCK_SELF ? vol : vol * (K_PI/6);
1044+
}
1045+
case GEOM PRISM: {
1046+
vector3_list vertices = o.subclass.prism_data->vertices_p;
1047+
double area = 0;
1048+
int i;
1049+
for (i = 0; i < vertices.num_items; ++i) {
1050+
int i1 = (i + 1) % vertices.num_items;
1051+
area += 0.5 * (vertices.items[i1].x - vertices.items[i].x) * (vertices.items[i1].y + vertices.items[i].y);
1052+
}
1053+
return fabs(area) * o.subclass.prism_data->height;
1054+
}
1055+
default:
1056+
return 0; /* unsupported object types? */
1057+
}
1058+
}
1059+
10191060
/**************************************************************************/
10201061
/**************************************************************************/
10211062

@@ -1353,6 +1394,12 @@ number overlap_with_object(geom_box b, int is_ellipsoid, geometric_object o,
13531394
unsigned i;
13541395

13551396
geom_get_bounding_box(o, &bb);
1397+
if (!is_ellipsoid &&
1398+
!empty_x && !empty_y && !empty_z && /* todo: optimize 1d and 2d cases */
1399+
bb.low.x >= b.low.x && bb.high.x <= b.high.x &&
1400+
bb.low.y >= b.low.y && bb.high.y <= b.high.y &&
1401+
bb.low.z >= b.low.z && bb.high.z <= b.high.z)
1402+
return geom_object_volume(o) / (V0 * fabs(matrix3x3_determinant(geometry_lattice.basis))); /* o is completely contained within b */
13561403
geom_box_intersection(&bb, &b, &bb);
13571404
if (bb.low.x > bb.high.x || bb.low.y > bb.high.y || bb.low.z > bb.high.z
13581405
|| (!empty_x && bb.low.x == bb.high.x)

utils/geomtst.c

Lines changed: 84 additions & 45 deletions
Original file line numberDiff line numberDiff line change
@@ -165,43 +165,42 @@ static double simple_ellip_overlap(geom_box b, geometric_object o, double tol)
165165
return olap0;
166166
}
167167

168-
static void test_overlap(double tol,
169-
number (*box_overlap_with_object)
170-
(geom_box b, geometric_object o,
171-
number tol, integer maxeval),
172-
double (*simple_overlap)
173-
(geom_box b, geometric_object o, double tol))
168+
geometric_object random_object_and_lattice(void)
174169
{
175170
geometric_object o = random_object();
176-
vector3 dir = random_unit_vector3();
177-
geom_box b;
178-
double d, olap, olap0;
179-
int dim;
180-
181171
#if 1
182172
geometry_lattice.basis1 = random_unit_vector3();
183173
geometry_lattice.basis2 = random_unit_vector3();
184174
geometry_lattice.basis3 = random_unit_vector3();
185175
geom_fix_lattice();
186176
geom_fix_object_ptr(&o);
187177
#endif
178+
return o;
179+
}
188180

189-
b.low = make_vector3(myurand(-1,0), myurand(-1,0), myurand(-1,0));
190-
b.high = make_vector3(myurand(0,1), myurand(0,1), myurand(0,1));
191-
192-
d = find_edge(o, dir, 10, tol);
193-
b.low = vector3_plus(b.low, vector3_scale(d, dir));
194-
b.high = vector3_plus(b.high, vector3_scale(d, dir));
195-
196-
dim = rand() % 3 + 1;
197-
if (dim < 3)
198-
b.low.z = b.high.z = 0;
199-
if (dim < 2)
200-
b.low.y = b.high.y = 0;
201-
202-
olap = box_overlap_with_object(b, o, tol/100, 10000/tol);
203-
olap0 = simple_overlap(b, o, tol/2);
181+
static const char *object_name(geometric_object o)
182+
{
183+
switch (o.which_subclass) {
184+
case CYLINDER:
185+
switch (o.subclass.cylinder_data->which_subclass) {
186+
case WEDGE: return "wedge";
187+
case CONE: return "cone";
188+
case CYLINDER_SELF: return "cylinder";
189+
}
190+
case SPHERE: return "sphere";
191+
case BLOCK:
192+
switch (o.subclass.block_data->which_subclass) {
193+
case ELLIPSOID: return "ellipsoid";
194+
case BLOCK_SELF: return "block";
195+
}
196+
case PRISM: return "prism";
197+
case COMPOUND_GEOMETRIC_OBJECT: return "compound object";
198+
default: return "geometric object";
199+
}
200+
}
204201

202+
void check_overlap(double tol, double olap0, double olap, int dim, geometric_object o, geom_box b)
203+
{
205204
if (fabs(olap0 - olap) > 2 * tol * fabs(olap)) {
206205
fprintf(stderr, "Large error %e in overlap (%g vs. %g) for:\n"
207206
" lattice = (%g,%g,%g), (%g,%g,%g), (%g,%g,%g)\n"
@@ -220,22 +219,59 @@ static void test_overlap(double tol,
220219
b.low.x, b.low.y, b.low.z,
221220
b.high.x, b.high.y, b.high.z);
222221
display_geometric_object_info(2, o);
223-
#if 1
224-
while (1) {
225-
tol /= sqrt(2.0);
226-
fprintf(stderr, "olap = %g, olap0 = %g (with tol = %e)\n",
227-
box_overlap_with_object(b, o, tol/100, 10000/tol),
228-
simple_overlap(b, o, tol/2), tol);
229-
}
230-
#endif
231-
exit(1);
222+
/* exit(1); */
232223
}
233224
else
234-
printf("Got %dd overlap %g vs. %g with tol = %e\n",
235-
dim,olap,olap0,tol);
225+
printf("Got %s %dd overlap %g vs. %g with tol = %e\n",
226+
object_name(o), dim,olap,olap0,tol);
227+
}
228+
229+
static void test_overlap(double tol,
230+
number (*box_overlap_with_object)
231+
(geom_box b, geometric_object o,
232+
number tol, integer maxeval),
233+
double (*simple_overlap)
234+
(geom_box b, geometric_object o, double tol))
235+
{
236+
geometric_object o = random_object_and_lattice();
237+
vector3 dir = random_unit_vector3();
238+
geom_box b;
239+
double d, olap, olap0;
240+
int dim;
241+
242+
b.low = make_vector3(myurand(-1,0), myurand(-1,0), myurand(-1,0));
243+
b.high = make_vector3(myurand(0,1), myurand(0,1), myurand(0,1));
244+
d = find_edge(o, dir, 10, tol);
245+
b.low = vector3_plus(b.low, vector3_scale(d, dir));
246+
b.high = vector3_plus(b.high, vector3_scale(d, dir));
247+
248+
dim = rand() % 3 + 1;
249+
if (dim < 3)
250+
b.low.z = b.high.z = 0;
251+
if (dim < 2)
252+
b.low.y = b.high.y = 0;
253+
254+
olap = box_overlap_with_object(b, o, tol/100, 10000/tol);
255+
olap0 = simple_overlap(b, o, tol/2);
256+
check_overlap(tol, olap0, olap, dim, o, b);
257+
geometric_object_destroy(o);
258+
}
259+
260+
static void test_volume(double tol)
261+
{
262+
geometric_object o = random_object_and_lattice();
263+
geom_box b;
264+
double olap1, olap2;
265+
266+
geom_get_bounding_box(o, &b);
267+
olap1 = box_overlap_with_object(b, o, tol/100, 10000/tol);
268+
b.low.x += 1e-7 * (b.high.x - b.low.x); /* b no longer contains o */
269+
olap2 = box_overlap_with_object(b, o, tol/100, 10000/tol);
270+
check_overlap(tol, olap1, olap2, 3, o, b);
236271
geometric_object_destroy(o);
237272
}
238273

274+
239275
/************************************************************************/
240276

241277
int main(void)
@@ -248,15 +284,18 @@ int main(void)
248284

249285
geom_initialize();
250286

287+
printf("**** whole box overlap: ****\n");
288+
for (i = 0; i < ntest; ++i)
289+
test_volume(tol);
251290
for (i = 0; i < ntest; ++i) {
252-
printf("**** box overlap: ****\n");
253-
test_overlap(tol,
254-
box_overlap_with_object,
255-
simple_overlap);
256-
printf("**** ellipsoid overlap: ****\n");
257-
test_overlap(tol,
258-
ellipsoid_overlap_with_object,
259-
simple_ellip_overlap);
291+
printf("**** box overlap: ****\n");
292+
test_overlap(tol,
293+
box_overlap_with_object,
294+
simple_overlap);
295+
printf("**** ellipsoid overlap: ****\n");
296+
test_overlap(tol,
297+
ellipsoid_overlap_with_object,
298+
simple_ellip_overlap);
260299
}
261300

262301
return 0;

0 commit comments

Comments
 (0)