Skip to content

Commit f42d41a

Browse files
Homer Reidstevengj
authored andcommitted
implement geom_fix_object for prisms (recompute centroid of polygon floor from center of geometric object); update test-prism to displace objects through random 3D vector (#27)
1 parent 0f73998 commit f42d41a

2 files changed

Lines changed: 66 additions & 39 deletions

File tree

utils/geom.c

Lines changed: 20 additions & 39 deletions
Original file line numberDiff line numberDiff line change
@@ -66,8 +66,6 @@ using namespace ctlio;
6666
#define MIN(a,b) ((a) < (b) ? (a) : (b))
6767

6868
// forward declarations of prism-related routines, at the bottom of this file
69-
static vector3 prism_vector_p2c(prism *prsm, vector3 vp);
70-
static vector3 prism_vector_c2p(prism *prsm, vector3 vc);
7169
static void get_prism_bounding_box(prism *prsm, geom_box *box);
7270
static double intersect_line_segment_with_prism(prism *prsm, vector3 p, vector3 d, double a, double b);
7371
static boolean point_in_polygon(double px, double py, vector3 *vertices, int num_vertices);
@@ -139,8 +137,14 @@ void geom_fix_object(geometric_object o)
139137
}
140138
case GEOM PRISM:
141139
{
140+
// recompute centroid of prism floor polygon from prism center,
141+
// which may have shifted since prism was initialized
142+
prism *prsm = o.subclass.prism_data;
143+
vector3 zhat = prsm->m_p2c.c2;
144+
double height = prsm->height;
145+
prsm->centroid = vector3_plus(o.center, vector3_scale(-0.5*height,zhat));
146+
break;
142147
}
143-
break;
144148
case GEOM COMPOUND_GEOMETRIC_OBJECT:
145149
{
146150
int i;
@@ -2462,36 +2466,6 @@ double min_distance_to_prism_roof_or_ceiling(vector3 p,
24622466
return sqrt(s*s+d*d);
24632467
}
24642468

2465-
/* utility routines for writing points, lines, quadrilaterals */
2466-
/* to text files for viewing in e.g. gnuplot */
2467-
void GPPoint(FILE *f, vector3 v, prism *prsm)
2468-
{ if (prsm)
2469-
v = prism_coordinate_p2c(prsm, v);
2470-
fprintf(f,"%e %e %e \n\n\n",v.x,v.y,v.z); }
2471-
2472-
void GPLine(FILE *f, vector3 v, vector3 l, prism *prsm)
2473-
{ if (prsm)
2474-
{ v = prism_coordinate_p2c(prsm, v);
2475-
l = prism_vector_p2c(prsm, l);
2476-
}
2477-
fprintf(f,"%e %e %e \n",v.x,v.y,v.z);
2478-
fprintf(f,"%e %e %e \n\n\n",v.x+l.x,v.y+l.y,v.z+l.z);
2479-
}
2480-
2481-
void GPQuad(FILE *f, vector3 v, vector3 l1, vector3 l2, prism *prsm)
2482-
{
2483-
if (prsm)
2484-
{ v = prism_coordinate_p2c(prsm, v);
2485-
l1 = prism_vector_p2c(prsm, l1);
2486-
l2 = prism_vector_p2c(prsm, l2);
2487-
}
2488-
fprintf(f,"%e %e %e \n",v.x,v.y,v.z);
2489-
fprintf(f,"%e %e %e \n",v.x+l1.x,v.y+l1.y,v.z+l1.z);
2490-
fprintf(f,"%e %e %e \n",v.x+l1.x+l2.x,v.y+l1.y+l2.y,v.z+l1.z+l2.z);
2491-
fprintf(f,"%e %e %e \n",v.x+l2.x,v.y+l2.y,v.z+l2.z);
2492-
fprintf(f,"%e %e %e \n\n\n",v.x,v.y,v.z);
2493-
}
2494-
24952469
/***************************************************************/
24962470
/* find the face of the prism for which the normal distance */
24972471
/* from x to the plane of that face is the shortest, then */
@@ -2600,13 +2574,13 @@ geometric_object make_prism(material_type material,
26002574

26012575
// make sure all vertices lie in a plane normal to the given axis
26022576
vector3 zhat = unit_vector3(axis);
2603-
double tolerance=1.0e-6;
2577+
double tol=1.0e-6;
26042578
for(nv=0; nv<num_vertices; nv++)
26052579
{ int nvp1 = (nv+1) % num_vertices;
26062580
vector3 zhatp = triangle_normal(centroid,vertices[nv],vertices[nvp1]);
26072581
boolean axis_normal
2608-
= ( vector3_nearly_equal(zhat, zhatp, tolerance)
2609-
|| vector3_nearly_equal(zhat, vector3_scale(-1.0,zhatp), tolerance)
2582+
= ( vector3_nearly_equal(zhat, zhatp, tol)
2583+
|| vector3_nearly_equal(zhat, vector3_scale(-1.0,zhatp), tol)
26102584
);
26112585
CHECK(axis_normal, "axis not normal to vertex plane in make_prism");
26122586
}
@@ -2615,14 +2589,21 @@ geometric_object make_prism(material_type material,
26152589
// to yield the coordinates of the same point in the prism coordinate system.
26162590
// the prism coordinate system is a right-handed coordinate system
26172591
// in which the prism lies in the xy plane (extrusion axis is the positive z-axis)
2618-
// with centroid at the origin and the first edge lying on the positive x-axis.
2592+
// with centroid at the origin.
26192593
// note: the prism *centroid* is the center of mass of the planar vertex polygon,
26202594
// i.e. it is a point lying on the bottom surface of the prism.
26212595
// This is the origin of coordinates in the prism system.
26222596
// The *center* of the geometric object is the center of mass of the
26232597
// 3D prism. So center = centroid + 0.5*zHat.
2624-
vector3 xhat = unit_vector3(vector3_minus(vertices[1],vertices[0]));
2625-
vector3 yhat = unit_vector3(vector3_cross(zhat,xhat));
2598+
vector3 x0hat={1.0,0.0,0.0}, y0hat={0.0,1.0,0.0}, z0hat={0.0,0.0,1.0};
2599+
vector3 xhat, yhat;
2600+
if (vector3_nearly_equal(zhat, x0hat, tol)) { xhat=y0hat; yhat=z0hat; }
2601+
else if (vector3_nearly_equal(zhat, y0hat, tol)) { xhat=z0hat; yhat=x0hat; }
2602+
else if (vector3_nearly_equal(zhat, z0hat, tol)) { xhat=x0hat; yhat=y0hat; }
2603+
else
2604+
{ xhat = unit_vector3(vector3_minus(vertices[1],vertices[0]));
2605+
yhat = unit_vector3(vector3_cross(zhat,xhat));
2606+
}
26262607
matrix3x3 m_p2c = {xhat, yhat, zhat };
26272608
matrix3x3 m_c2p = matrix3x3_inverse(m_p2c);
26282609

utils/test-prism.c

Lines changed: 46 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -40,6 +40,41 @@ boolean point_in_or_on_prism(prism *prsm, vector3 xc, boolean include_boundaries
4040
// routine from geom.c that rotates the coordinate of a point
4141
// from the prism coordinate system to the cartesian coordinate system
4242
vector3 prism_coordinate_p2c(prism *prsm, vector3 vp);
43+
vector3 prism_coordinate_c2p(prism *prsm, vector3 vc);
44+
vector3 prism_vector_p2c(prism *prsm, vector3 vp);
45+
vector3 prism_vector_c2p(prism *prsm, vector3 vc);
46+
47+
/***************************************************************/
48+
/* utility routines for writing points, lines, quadrilaterals */
49+
/* to text files for viewing in e.g. gnuplot */
50+
/***************************************************************/
51+
void GPPoint(FILE *f, vector3 v, prism *prsm)
52+
{ if (prsm)
53+
v = prism_coordinate_p2c(prsm, v);
54+
fprintf(f,"%e %e %e \n\n\n",v.x,v.y,v.z); }
55+
56+
void GPLine(FILE *f, vector3 v, vector3 l, prism *prsm)
57+
{ if (prsm)
58+
{ v = prism_coordinate_p2c(prsm, v);
59+
l = prism_vector_p2c(prsm, l);
60+
}
61+
fprintf(f,"%e %e %e \n",v.x,v.y,v.z);
62+
fprintf(f,"%e %e %e \n\n\n",v.x+l.x,v.y+l.y,v.z+l.z);
63+
}
64+
65+
void GPQuad(FILE *f, vector3 v, vector3 l1, vector3 l2, prism *prsm)
66+
{
67+
if (prsm)
68+
{ v = prism_coordinate_p2c(prsm, v);
69+
l1 = prism_vector_p2c(prsm, l1);
70+
l2 = prism_vector_p2c(prsm, l2);
71+
}
72+
fprintf(f,"%e %e %e \n",v.x,v.y,v.z);
73+
fprintf(f,"%e %e %e \n",v.x+l1.x,v.y+l1.y,v.z+l1.z);
74+
fprintf(f,"%e %e %e \n",v.x+l1.x+l2.x,v.y+l1.y+l2.y,v.z+l1.z+l2.z);
75+
fprintf(f,"%e %e %e \n",v.x+l2.x,v.y+l2.y,v.z+l2.z);
76+
fprintf(f,"%e %e %e \n\n\n",v.x,v.y,v.z);
77+
}
4378

4479
/***************************************************************/
4580
/***************************************************************/
@@ -383,6 +418,17 @@ int run_unit_tests()
383418
geometric_object the_block = make_block(m, c, xhat, yhat, zhat, size);
384419
geometric_object the_prism=make_prism(m, v, 4, LZ, zhat);
385420

421+
/***************************************************************/
422+
/* with probability P_SHIFT, shift the centers of both block */
423+
/* and prism by a random displacement vector */
424+
/***************************************************************/
425+
#define P_SHIFT 0.75
426+
if ( urand(0.0,1.0) < P_SHIFT )
427+
{ vector3 shift = vector3_scale( urand(0.0,1.0), random_unit_vector3() );
428+
the_block.center = vector3_plus(the_block.center, shift);
429+
the_prism.center = vector3_plus(the_prism.center, shift);
430+
}
431+
386432
char *s=getenv("LIBCTL_TEST_PRISM_LOG");
387433
int write_log = (s && s[0]=='1') ? 1 : 0;
388434

0 commit comments

Comments
 (0)