From 170281576465f2e0ab03b103ca7f999d758d76ef Mon Sep 17 00:00:00 2001 From: danielwboyce Date: Tue, 7 Jan 2020 13:11:37 -0700 Subject: [PATCH 01/63] added sidewall_angle property in scheme --- utils/geom.scm | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/utils/geom.scm b/utils/geom.scm index 3098a02..8fad959 100644 --- a/utils/geom.scm +++ b/utils/geom.scm @@ -127,7 +127,8 @@ (define-property centroid (vector3 0 0 0) 'vector3) (define-property workspace '() (make-list-type 'number)) (define-property m_c2p identity_matrix 'matrix3x3) - (define-property m_p2c identity_matrix 'matrix3x3)) + (define-property m_p2c identity_matrix 'matrix3x3) + (define-property sidewall_angle 0 'number)) (define-class ellipsoid block (define-derived-property inverse-semi-axes 'vector3 From ff0dfa82f5ac17f276bd66c746fd6852182f8846 Mon Sep 17 00:00:00 2001 From: danielwboyce Date: Tue, 7 Jan 2020 14:59:27 -0700 Subject: [PATCH 02/63] changes to add sidewall_angle --- utils/ctlgeom.h | 4 ++-- utils/geom.c | 14 +++++++++++--- utils/test-prism.c | 4 ++-- 3 files changed, 15 insertions(+), 7 deletions(-) diff --git a/utils/ctlgeom.h b/utils/ctlgeom.h index 6fe2bba..b9145e9 100644 --- a/utils/ctlgeom.h +++ b/utils/ctlgeom.h @@ -157,12 +157,12 @@ extern boolean node_in_or_on_polygon(vector3 q0, vector3 *nodes, int num_nodes, // prism with `center` field computed automatically from vertices, height, axis GEOMETRIC_OBJECT make_prism(MATERIAL_TYPE material, const vector3 *vertices, int num_vertices, - double height, vector3 axis); + double height, vector3 axis, double sidewall_angle); // as make_prism, but with a rigid translation so that the prism is centered at center GEOMETRIC_OBJECT make_prism_with_center(MATERIAL_TYPE material, vector3 center, const vector3 *vertices, int num_vertices, double height, - vector3 axis); + vector3 axis, double sidewall_angle); int vector3_nearly_equal(vector3 v1, vector3 v2, double tolerance); diff --git a/utils/geom.c b/utils/geom.c index 7883232..85a5b97 100644 --- a/utils/geom.c +++ b/utils/geom.c @@ -913,6 +913,7 @@ double geom_object_volume(GEOMETRIC_OBJECT o) { return o.subclass.block_data->which_subclass == BLK BLOCK_SELF ? vol : vol * (K_PI / 6); } case GEOM PRISM: { + // needs updating for non-normal sidewalls vector3_list vertices = o.subclass.prism_data->vertices_p; double area = 0; int i; @@ -2490,6 +2491,11 @@ void init_prism(geometric_object *o) { vertices[nv] = vector3_plus(vertices[nv], shift); centroid = vector3_plus(centroid, shift); } + + // This section will be for performing calculations with the sidewall angle + if (isnan(prsm->sidewall_angle)) { + prsm->sidewall_angle = 0.0; + } // compute rotation matrix that operates on a vector of cartesian coordinates // to yield the coordinates of the same point in the prism coordinate system. @@ -2540,14 +2546,15 @@ void init_prism(geometric_object *o) { /***************************************************************/ // prism with center determined automatically from vertices, height, and axis geometric_object make_prism(material_type material, const vector3 *vertices, int num_vertices, - double height, vector3 axis) { - return make_prism_with_center(material, auto_center, vertices, num_vertices, height, axis); + double height, vector3 axis, double sidewall_angle) { + return make_prism_with_center(material, auto_center, vertices, num_vertices, height, axis, + sidewall_angle); } // prism in which all vertices are translated to ensure that the prism is centered at center geometric_object make_prism_with_center(material_type material, vector3 center, const vector3 *vertices, int num_vertices, double height, - vector3 axis) { + vector3 axis, double sidewall_angle) { geometric_object o = make_geometric_object(material, center); o.which_subclass = GEOM PRISM; prism *prsm = o.subclass.prism_data = MALLOC1(prism); @@ -2558,6 +2565,7 @@ geometric_object make_prism_with_center(material_type material, vector3 center, memcpy(prsm->vertices.items, vertices, num_vertices * sizeof(vector3)); prsm->height = height; prsm->axis = axis; + prsm->sidewall_angle = sidewall_angle; init_prism(&o); return o; } diff --git a/utils/test-prism.c b/utils/test-prism.c index 12eb0b5..8d17093 100644 --- a/utils/test-prism.c +++ b/utils/test-prism.c @@ -484,7 +484,7 @@ int run_unit_tests() { v[3].z = -0.5 * LZ; geometric_object the_block = make_block(m, c, xhat, yhat, zhat, size); - geometric_object the_prism = make_prism(m, v, 4, LZ, zhat); + geometric_object the_prism = make_prism(m, v, 4, LZ, zhat, 0.0); /***************************************************************/ /* with probability P_SHIFT, shift the centers of both block */ @@ -625,7 +625,7 @@ int main(int argc, char *argv[]) { } fclose(f); - geometric_object the_prism = make_prism(NULL, vertices, num_vertices, height, axis); + geometric_object the_prism = make_prism(NULL, vertices, num_vertices, height, axis, 0.0); prism *prsm = the_prism.subclass.prism_data; prism2gmsh(prsm, "test-prism.pp"); prism2gnuplot(prsm, "test-prism.gp"); From d6fb958d201d15974b530b831e367bfe9d9bd7f9 Mon Sep 17 00:00:00 2001 From: danielwboyce Date: Tue, 7 Jan 2020 16:16:23 -0700 Subject: [PATCH 03/63] started trying to add transformation matrix but realized it may not be an affine transformation after all --- utils/geom.c | 14 +++++++++++++- 1 file changed, 13 insertions(+), 1 deletion(-) diff --git a/utils/geom.c b/utils/geom.c index 85a5b97..f6d0151 100644 --- a/utils/geom.c +++ b/utils/geom.c @@ -2404,6 +2404,7 @@ void display_prism_info(int indentby, geometric_object *o) { int vector3_nearly_equal(vector3 v1, vector3 v2, double tolerance) { return (vector3_norm(vector3_minus(v1, v2)) <= tolerance * vector3_norm(v1)); } +matrix3x3 sidewall_scaling_matrix; /***************************************************************/ /* return the unit normal vector to the triangle with the given*/ @@ -2494,8 +2495,19 @@ void init_prism(geometric_object *o) { // This section will be for performing calculations with the sidewall angle if (isnan(prsm->sidewall_angle)) { - prsm->sidewall_angle = 0.0; + prsm->sidewall_angle = 0.0; } + double cx, cy; // Scaling factors in the x- and -y dimensions based on the sidewall angle + if (sidewall_angle == 0.0) { + // If the sidewall_angle denotes a normal sidewall, the transformation matrix + // is simply the identity matrix. + cx = 1; + cy = 1; + } + else if (sidewall_angle > 0.0) { + cx = 1 - prism->height + } + matrix3x3 // compute rotation matrix that operates on a vector of cartesian coordinates // to yield the coordinates of the same point in the prism coordinate system. From d4e35b2e9305b9d8cbdea015d815edfe6b472a9f Mon Sep 17 00:00:00 2001 From: danielwboyce Date: Thu, 9 Jan 2020 16:15:52 -0700 Subject: [PATCH 04/63] Coordinate transform functions have been updated to account for a non-normal sidewall angle. First attempt. --- utils/geom.c | 57 ++++++++++++++++++++++++++++++++++------------------ 1 file changed, 38 insertions(+), 19 deletions(-) diff --git a/utils/geom.c b/utils/geom.c index f6d0151..2e4b821 100644 --- a/utils/geom.c +++ b/utils/geom.c @@ -1925,22 +1925,52 @@ geometric_object make_ellipsoid(material_type material, vector3 center, vector3 /***************************************************************/ /* given coordinates of a point in the prism coordinate system,*/ -/* return cartesian coordinates of that point */ +/* return cartesian coordinates of that point includes calcu- */ +/* lations to account for the sidewall angle */ /***************************************************************/ +matrix3x3 prism_projective_transformation_for_p2c(prism *prsm, vector3 pp) { + matrix3x3 c2p; + double cx; + double cy; + double theta = (K_PI / 2) - prsm->sidewall_angle; + if (prsm->sidewall_angle == 0) { + cx = 1; + cy = 1; + + } + if (pp.x == 0) { + cx = 0; + } + else { + cx = 1 - pp.z / (pp.x * tan(theta)) + } + c2p = {{cx, 0, 0}, {0, cy, 0}, {0, 0, 1}}; + return c2p; +} + +matrix3x3 prism_projective_transformation_for_c2p(prism *prsm, vector3 pc) { + matrix3x3 p2c = matrix3x3_inverse(prism_projective_transformation_for_c2p(prsm, pc)); + return p2c; +} + vector3 prism_coordinate_p2c(prism *prsm, vector3 pp) { - return vector3_plus(prsm->centroid, matrix3x3_vector3_mult(prsm->m_p2c, pp)); + matrix3x3 projective_transform_p2c = prism_projective_transformation_for_p2c(prsm, pp); + return vector3_plus(prsm->centroid, matrix3x3_vector3_mult(matrix3x3_mult(prsm->m_p2c, projective_transform_p2c), pp)); } vector3 prism_vector_p2c(prism *prsm, vector3 vp) { - return matrix3x3_vector3_mult(prsm->m_p2c, vp); + matrix3x3 projective_transform_p2c = prism_projective_transformation_for_p2c(prsm, pp); + return matrix3x3_vector3_mult(matrix3x3_mult(prsm->m_p2c, projective_transform_p2c), vp); } vector3 prism_coordinate_c2p(prism *prsm, vector3 pc) { - return matrix3x3_vector3_mult(prsm->m_c2p, vector3_minus(pc, prsm->centroid)); + matrix3x3 projective_transform_c2p = prism_projective_transformation_for_c2p(prsm, pp); + return matrix3x3_vector3_mult(matrix3x3_mult(prsm->m_p2c, projective_transform_c2p), vector3_minus(pc, prsm->centroid)); } vector3 prism_vector_c2p(prism *prsm, vector3 vc) { - return matrix3x3_vector3_mult(prsm->m_c2p, vc); + matrix3x3 projective_transform_c2p = prism_projective_transformation_for_c2p(prsm, pp); + return matrix3x3_vector3_mult(matrix3x3_mult(prsm->m_p2c, projective_transform_c2p), vc); } /***************************************************************/ @@ -2391,8 +2421,8 @@ void display_prism_info(int indentby, geometric_object *o) { vector3 *vs = prsm->vertices.items; int num_vertices = prsm->vertices.num_items; - ctl_printf("%*s height %g, axis (%g,%g,%g), %i vertices:\n", indentby, "", prsm->height, - prsm->axis.x, prsm->axis.y, prsm->axis.z, num_vertices); + ctl_printf("%*s height %g, axis (%g,%g,%g), sidewall angle: %g radians, %i vertices:\n", indentby, "", prsm->height, + prsm->axis.x, prsm->axis.y, prsm->axis.z, prsm->sidewall_angle, num_vertices); int nv; for (nv = 0; nv < num_vertices; nv++) ctl_printf("%*s (%g,%g,%g)\n", indentby, "", vs[nv].x, vs[nv].y, vs[nv].z); @@ -2493,21 +2523,10 @@ void init_prism(geometric_object *o) { centroid = vector3_plus(centroid, shift); } - // This section will be for performing calculations with the sidewall angle + // This section checks if the sidewall_angle has been initialized if (isnan(prsm->sidewall_angle)) { prsm->sidewall_angle = 0.0; } - double cx, cy; // Scaling factors in the x- and -y dimensions based on the sidewall angle - if (sidewall_angle == 0.0) { - // If the sidewall_angle denotes a normal sidewall, the transformation matrix - // is simply the identity matrix. - cx = 1; - cy = 1; - } - else if (sidewall_angle > 0.0) { - cx = 1 - prism->height - } - matrix3x3 // compute rotation matrix that operates on a vector of cartesian coordinates // to yield the coordinates of the same point in the prism coordinate system. From 2ff3d4a3e2f76ceb7bf862021fab5fe505ad970f Mon Sep 17 00:00:00 2001 From: danielwboyce Date: Thu, 9 Jan 2020 16:56:52 -0700 Subject: [PATCH 05/63] The prism_projective_transformation_for_* functions won't work on prism_vector_* calculations because the vectors that are being transformed don't have a particular location. We'll need to try something else. --- utils/geom.c | 23 +++++++++++++++++------ 1 file changed, 17 insertions(+), 6 deletions(-) diff --git a/utils/geom.c b/utils/geom.c index 2e4b821..56180d1 100644 --- a/utils/geom.c +++ b/utils/geom.c @@ -1942,9 +1942,14 @@ matrix3x3 prism_projective_transformation_for_p2c(prism *prsm, vector3 pp) { cx = 0; } else { - cx = 1 - pp.z / (pp.x * tan(theta)) + cx = 1 - pp.z / (pp.x * tan(theta)); } - c2p = {{cx, 0, 0}, {0, cy, 0}, {0, 0, 1}}; + vector3 c0vector = {cx, 0, 0}; + c2p.c0 = c0vector; + vector3 c1vector = {0, cy, 0}; + c2p.c1 = c1vector; + vector3 c2vector = {0, 0, 1}; + c2p.c2 = c2vector; return c2p; } @@ -1958,9 +1963,12 @@ vector3 prism_coordinate_p2c(prism *prsm, vector3 pp) { return vector3_plus(prsm->centroid, matrix3x3_vector3_mult(matrix3x3_mult(prsm->m_p2c, projective_transform_p2c), pp)); } +// the prism_projective_transformation_for_p2c() function won't work +// here because vp isn't actually at a particular location vector3 prism_vector_p2c(prism *prsm, vector3 vp) { - matrix3x3 projective_transform_p2c = prism_projective_transformation_for_p2c(prsm, pp); - return matrix3x3_vector3_mult(matrix3x3_mult(prsm->m_p2c, projective_transform_p2c), vp); + // matrix3x3 projective_transform_p2c = prism_projective_transformation_for_p2c(prsm, pp); + // return matrix3x3_vector3_mult(matrix3x3_mult(prsm->m_p2c, projective_transform_p2c), vp); + return matrix3x3_vector3_mult(prsm->m_p2c, vp); } vector3 prism_coordinate_c2p(prism *prsm, vector3 pc) { @@ -1968,9 +1976,12 @@ vector3 prism_coordinate_c2p(prism *prsm, vector3 pc) { return matrix3x3_vector3_mult(matrix3x3_mult(prsm->m_p2c, projective_transform_c2p), vector3_minus(pc, prsm->centroid)); } +// the prism_projective_transformation_for_c2p() function won't work +// here because vp isn't actually at a particular location vector3 prism_vector_c2p(prism *prsm, vector3 vc) { - matrix3x3 projective_transform_c2p = prism_projective_transformation_for_c2p(prsm, pp); - return matrix3x3_vector3_mult(matrix3x3_mult(prsm->m_p2c, projective_transform_c2p), vc); + // matrix3x3 projective_transform_c2p = prism_projective_transformation_for_c2p(prsm, pp); + // return matrix3x3_vector3_mult(matrix3x3_mult(prsm->m_p2c, projective_transform_c2p), vc); + return matrix3x3_vector3_mult(prsm->m_c2p, vc); } /***************************************************************/ From a18601f77b0cee9aee7373c8c392da273ffa4c82 Mon Sep 17 00:00:00 2001 From: danielwboyce Date: Thu, 9 Jan 2020 16:57:46 -0700 Subject: [PATCH 06/63] Added another unit test to save prisms with and without normal sidewall angles to separate GNU plot files --- utils/test-prism.c | 28 ++++++++++++++++++++++++++++ 1 file changed, 28 insertions(+) diff --git a/utils/test-prism.c b/utils/test-prism.c index 8d17093..96a11d6 100644 --- a/utils/test-prism.c +++ b/utils/test-prism.c @@ -449,6 +449,34 @@ int test_point_in_polygon(int write_log) { return num_failed; } +/************************************************************************/ +/* fifth unit test: saves a prism with normal sidewall angle and a */ +/* prism with the same base polygon with non-normal sidewall angle to */ +/* separate GNU plot files */ +/************************************************************************/ +int test_sidewall_prisms_to_gnuplot() { + void *m = NULL; + + int num_nodes = 4; + vector3 nodes[num_nodes]; + nodes[0] = make_vector3(1.0, 1.0, 0.0); + nodes[1] = make_vector3(1.0, -1.0, 0.0); + nodes[2] = make_vector3(-1.0, -1.0, 0.0); + nodes[3] = make_vector3(-1.0, 1.0, 0.0); + + double height = 10; + vector3 zhat = make_vector3(0, 0, 1); + double normal_sidewall = 0; + geometric_object normal_sidewall_prism = make_prism(m, nodes, num_nodes, height, zhat, normal_sidewall); + double ten_degree_sidewall = 10.0 * 2 * K_PI / 360.0; + geometric_object ten_degree_sidewall_prism = make_prism(m, nodes, num_nodes, height, zhat, ten_degree_sidewall); + + prism2gnuplot(normal_sidewall_prism, "normal_sidewall_gnu_plot.dat"); + prism2gnuplot(normal_sidewall_prism, "ten_degree_sidewall_gnu_plot.dat"); + + return 0; +} + /***************************************************************/ /* unit tests: create the same parallelepiped two ways (as a */ /* block and as a prism) and verify that geometric primitives */ From ff33e65de8bad8ea695a66682d3b445b77296890 Mon Sep 17 00:00:00 2001 From: danielwboyce Date: Thu, 9 Jan 2020 17:31:48 -0700 Subject: [PATCH 07/63] Fixed a compilation error --- utils/geom.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/utils/geom.c b/utils/geom.c index 56180d1..204a60f 100644 --- a/utils/geom.c +++ b/utils/geom.c @@ -1972,7 +1972,7 @@ vector3 prism_vector_p2c(prism *prsm, vector3 vp) { } vector3 prism_coordinate_c2p(prism *prsm, vector3 pc) { - matrix3x3 projective_transform_c2p = prism_projective_transformation_for_c2p(prsm, pp); + matrix3x3 projective_transform_c2p = prism_projective_transformation_for_c2p(prsm, pc); return matrix3x3_vector3_mult(matrix3x3_mult(prsm->m_p2c, projective_transform_c2p), vector3_minus(pc, prsm->centroid)); } From b7ce926a9c78094f9d851847facd848f662621c3 Mon Sep 17 00:00:00 2001 From: danielwboyce Date: Thu, 9 Jan 2020 17:32:06 -0700 Subject: [PATCH 08/63] Fixed a compilation error --- utils/test-prism.c | 11 ++++++++--- 1 file changed, 8 insertions(+), 3 deletions(-) diff --git a/utils/test-prism.c b/utils/test-prism.c index 96a11d6..4be289d 100644 --- a/utils/test-prism.c +++ b/utils/test-prism.c @@ -466,13 +466,17 @@ int test_sidewall_prisms_to_gnuplot() { double height = 10; vector3 zhat = make_vector3(0, 0, 1); + double normal_sidewall = 0; - geometric_object normal_sidewall_prism = make_prism(m, nodes, num_nodes, height, zhat, normal_sidewall); + geometric_object normal_sidewall_geom_object = make_prism(m, nodes, num_nodes, height, zhat, normal_sidewall); + prism *normal_sidewall_prism = normal_sidewall_geom_object.subclass.prism_data; + double ten_degree_sidewall = 10.0 * 2 * K_PI / 360.0; - geometric_object ten_degree_sidewall_prism = make_prism(m, nodes, num_nodes, height, zhat, ten_degree_sidewall); + geometric_object ten_degree_sidewall_geom_object = make_prism(m, nodes, num_nodes, height, zhat, ten_degree_sidewall); + prism *ten_degree_sidewall_prism = normal_sidewall_geom_object.subclass.prism_data; prism2gnuplot(normal_sidewall_prism, "normal_sidewall_gnu_plot.dat"); - prism2gnuplot(normal_sidewall_prism, "ten_degree_sidewall_gnu_plot.dat"); + prism2gnuplot(ten_degree_sidewall_prism, "ten_degree_sidewall_gnu_plot.dat"); return 0; } @@ -537,6 +541,7 @@ int run_unit_tests() { int num_failed_2 = 0; // test_normal_to_object(the_block, the_prism, NUMLINES, write_log); int num_failed_3 = test_line_segment_intersection(the_block, the_prism, NUMLINES, write_log); int num_failed_4 = test_point_in_polygon(write_log); + int num_failed_5 = test_sidewall_prisms_to_gnuplot(); return num_failed_1 + num_failed_2 + num_failed_3 + num_failed_4; } From 5c37bd0e690598cabc4df471bcc3a38be80000d8 Mon Sep 17 00:00:00 2001 From: danielwboyce Date: Sun, 12 Jan 2020 13:45:45 -0700 Subject: [PATCH 09/63] Reverted changes to prism_coordinate_p2c(), prism_vector_p2c(), prism_coordinate_c2p(), and prism_vector_c2p(). --- utils/geom.c | 49 ++++--------------------------------------------- 1 file changed, 4 insertions(+), 45 deletions(-) diff --git a/utils/geom.c b/utils/geom.c index 204a60f..af97b26 100644 --- a/utils/geom.c +++ b/utils/geom.c @@ -1925,63 +1925,22 @@ geometric_object make_ellipsoid(material_type material, vector3 center, vector3 /***************************************************************/ /* given coordinates of a point in the prism coordinate system,*/ -/* return cartesian coordinates of that point includes calcu- */ -/* lations to account for the sidewall angle */ +/* return cartesian coordinates of that point */ /***************************************************************/ -matrix3x3 prism_projective_transformation_for_p2c(prism *prsm, vector3 pp) { - matrix3x3 c2p; - double cx; - double cy; - double theta = (K_PI / 2) - prsm->sidewall_angle; - if (prsm->sidewall_angle == 0) { - cx = 1; - cy = 1; - - } - if (pp.x == 0) { - cx = 0; - } - else { - cx = 1 - pp.z / (pp.x * tan(theta)); - } - vector3 c0vector = {cx, 0, 0}; - c2p.c0 = c0vector; - vector3 c1vector = {0, cy, 0}; - c2p.c1 = c1vector; - vector3 c2vector = {0, 0, 1}; - c2p.c2 = c2vector; - return c2p; -} - -matrix3x3 prism_projective_transformation_for_c2p(prism *prsm, vector3 pc) { - matrix3x3 p2c = matrix3x3_inverse(prism_projective_transformation_for_c2p(prsm, pc)); - return p2c; -} - vector3 prism_coordinate_p2c(prism *prsm, vector3 pp) { - matrix3x3 projective_transform_p2c = prism_projective_transformation_for_p2c(prsm, pp); - return vector3_plus(prsm->centroid, matrix3x3_vector3_mult(matrix3x3_mult(prsm->m_p2c, projective_transform_p2c), pp)); + return vector3_plus(prsm->centroid, matrix3x3_vector3_mult(prsm->m_p2c, pp)); } -// the prism_projective_transformation_for_p2c() function won't work -// here because vp isn't actually at a particular location vector3 prism_vector_p2c(prism *prsm, vector3 vp) { - // matrix3x3 projective_transform_p2c = prism_projective_transformation_for_p2c(prsm, pp); - // return matrix3x3_vector3_mult(matrix3x3_mult(prsm->m_p2c, projective_transform_p2c), vp); return matrix3x3_vector3_mult(prsm->m_p2c, vp); } vector3 prism_coordinate_c2p(prism *prsm, vector3 pc) { - matrix3x3 projective_transform_c2p = prism_projective_transformation_for_c2p(prsm, pc); - return matrix3x3_vector3_mult(matrix3x3_mult(prsm->m_p2c, projective_transform_c2p), vector3_minus(pc, prsm->centroid)); + return matrix3x3_vector3_mult(prsm->m_c2p, vector3_minus(pc, prsm->centroid)); } -// the prism_projective_transformation_for_c2p() function won't work -// here because vp isn't actually at a particular location vector3 prism_vector_c2p(prism *prsm, vector3 vc) { - // matrix3x3 projective_transform_c2p = prism_projective_transformation_for_c2p(prsm, pp); - // return matrix3x3_vector3_mult(matrix3x3_mult(prsm->m_p2c, projective_transform_c2p), vc); - return matrix3x3_vector3_mult(prsm->m_c2p, vc); + return matrix3x3_vector3_mult(prsm->m_c2p, vc); } /***************************************************************/ From 6564979c4b25ab33864c922deef12e3d8d91e78a Mon Sep 17 00:00:00 2001 From: danielwboyce Date: Sun, 12 Jan 2020 14:02:38 -0700 Subject: [PATCH 10/63] * Addition of some derived values. This will increase the memory usage of a prism object; the list of derived values may be shorted later. * Addition of a comment to geom.scm giving a brief explanation of what sidewall_angle does. --- utils/geom.scm | 15 ++++++++++++--- 1 file changed, 12 insertions(+), 3 deletions(-) diff --git a/utils/geom.scm b/utils/geom.scm index 8fad959..17571d5 100644 --- a/utils/geom.scm +++ b/utils/geom.scm @@ -92,7 +92,7 @@ ; some notes regarding prisms: ; (a) When instantiating a prism, typically only the -; fields `vertices`, `height,` and (optionally) `axis` +; fields `vertices`, `height,` `sidewall_angle`, and (optionally) `axis` ; will be initialized by the user; all remaining fields are ; derived properties that are computed internally. (So, morally ; they should be thought of as having been declared using @@ -117,18 +117,27 @@ ; (center = centroid + 0.5*height*axis), so---in contrast to all other ; types of geometric-object---there is no need to specify the `center` ; field when instantiating a prism. +; (f) The sidwall angle determines an angle at which the prism is extruded. +; A positive sidewall angle determines a prism that extrudes inward at +; the given angle, and a negative sidewall angle determines a prisms +; that extrudes outward. This is useful for modeling a prism formed in +; a foundry that cannot grow objects with a perfectly normal sidewall. (define-class prism geometric-object ; fields to be filled in by users (define-property vertices '() (make-list-type 'vector3)) (define-property height 0 'number) (define-property axis (vector3 0 0 0) 'vector3) + (define-property sidewall_angle 0 'number) ; derived fields computed internally (define-property vertices_p '() (make-list-type 'vector3)) + (define-property top_polygon_diff_vectors '() (make-list-type 'vector3)) + (define-property top_polygon_diff_vectors_scaled '() (make-list-type 'vector3)) + (define-property top_polygon_diff_vectors_p '() (make-list-type 'vector3)) + (define-property top_polygon_diff_vectors_scaled_p '() (make-list-type 'vector3)) (define-property centroid (vector3 0 0 0) 'vector3) (define-property workspace '() (make-list-type 'number)) (define-property m_c2p identity_matrix 'matrix3x3) - (define-property m_p2c identity_matrix 'matrix3x3) - (define-property sidewall_angle 0 'number)) + (define-property m_p2c identity_matrix 'matrix3x3)) (define-class ellipsoid block (define-derived-property inverse-semi-axes 'vector3 From 030a13313786647316f41269976e09120a493346 Mon Sep 17 00:00:00 2001 From: danielwboyce Date: Sun, 12 Jan 2020 15:24:57 -0700 Subject: [PATCH 11/63] Calculated difference vectors in init_prism() --- utils/geom.c | 62 +++++++++++++++++++++++++++++++++++++++++++++++----- 1 file changed, 57 insertions(+), 5 deletions(-) diff --git a/utils/geom.c b/utils/geom.c index af97b26..ba0ef23 100644 --- a/utils/geom.c +++ b/utils/geom.c @@ -2492,11 +2492,6 @@ void init_prism(geometric_object *o) { vertices[nv] = vector3_plus(vertices[nv], shift); centroid = vector3_plus(centroid, shift); } - - // This section checks if the sidewall_angle has been initialized - if (isnan(prsm->sidewall_angle)) { - prsm->sidewall_angle = 0.0; - } // compute rotation matrix that operates on a vector of cartesian coordinates // to yield the coordinates of the same point in the prism coordinate system. @@ -2536,6 +2531,63 @@ void init_prism(geometric_object *o) { for (nv = 0; nv < num_vertices; nv++) prsm->vertices_p.items[nv] = prism_coordinate_c2p(prsm, vertices[nv]); + // calculate difference vectors between bottom polygon and the top polygon, where + // * the bottom polygon is the one passed in to the the make_prism() function, + // stored in vertices and vertices_p + // * the top polygon is the top surface (parallel to the bottom polygon) resulting + // from the extrusion of the bottom polygon. Whether or not the extrusion tapers + // is dependent on the value of sidewall_angle. + // ** The value of each of the top polygon vertices can be found + // vertices_p + top_polygon_diff_vectors_p + // vertices + top_polygon_diff_vectors + // ** A linearly interpolated value of the polygon vertices between the bottom + // polygon and the top can be found + // vertices_p + top_polygon_diff_vectors_scaled_p * z + if (isnan(prsm->sidewall_angle)) { + prsm->sidewall_angle = 0.0; + } + double theta = (K_PI/2) - prsm->sidewall_angle; + + prsm->top_polygon_diff_vectors_p.num_items = num_vertices; + prsm->top_polygon_diff_vectors_p.items = (vector3 *)malloc(num_vertices * sizeof(vector3)); + for (nv = 0; nv < num_vertices; nv++) { + double cx; + double cy; + if (prsm->vertices_p.items[nv].x == 0) { + cx = 0; + } + else { + cx = 1 - prsm->height / (prsm->vertices_p.items[nv].x * tan(theta)); + } + if (prsm->vertices_p.items[nv].y == 0) { + cy = 0; + } + else { + cy = 1 - prsm->height / (prsm->vertices_p.items[nv].y * tan(theta)); + } + prsm->top_polygon_diff_vectors_p.items[nv].x = (cx - 1) * prsm->vertices_p.items[nv].x; + prsm->top_polygon_diff_vectors_p.items[nv].y = (cy - 1) * prsm->vertices_p.items[nv].y; + prsm->top_polygon_diff_vectors_p.items[nv].z = prsm->height - prsm->vertices_p.items[nv].z; + } + + prsm->top_polygon_diff_vectors_scaled_p.num_items = num_vertices; + prsm->top_polygon_diff_vectors_scaled_p.items = (vector3 *)malloc(num_vertices * sizeof(vector3)); + for (nv = 0; nv < num_vertices; nv++) { + prsm->top_polygon_diff_vectors_scaled_p.items[nv] = vector3_scale(1/prsm->height, prsm->top_polygon_diff_vectors_p.items[nv]); + } + + prsm->top_polygon_diff_vectors.num_items = num_vertices; + prsm->top_polygon_diff_vectors.items = (vector3 *)malloc(num_vertices * sizeof(vector3)); + for (nv = 0; nv < num_vertices; nv++) { + prsm->top_polygon_diff_vectors.items[nv] = prism_vector_p2c(prsm, prsm->top_polygon_diff_vectors_p.items[nv]); + } + + prsm->top_polygon_diff_vectors_scaled.num_items = num_vertices; + prsm->top_polygon_diff_vectors_scaled.items = (vector3 *)malloc(num_vertices * sizeof(vector3)); + for (nv = 0; nv < num_vertices; nv++) { + prsm->top_polygon_diff_vectors_scaled.items[nv] = prism_vector_p2c(prsm, prsm->top_polygon_diff_vectors_scaled_p.items[nv]); + } + // workspace is an internally-stored double-valued array of length num_vertices+2 // that is used by some geometry routines prsm->workspace.num_items = num_vertices + 2; From 55e3871a78890cd85ed133b4170c85363f904abd Mon Sep 17 00:00:00 2001 From: danielwboyce Date: Sun, 12 Jan 2020 15:54:31 -0700 Subject: [PATCH 12/63] Correction for case where sidewall_angle==0 (would have blown up tangent calculation) --- utils/geom.c | 14 +++++++++++--- 1 file changed, 11 insertions(+), 3 deletions(-) diff --git a/utils/geom.c b/utils/geom.c index ba0ef23..be80112 100644 --- a/utils/geom.c +++ b/utils/geom.c @@ -2552,19 +2552,27 @@ void init_prism(geometric_object *o) { prsm->top_polygon_diff_vectors_p.items = (vector3 *)malloc(num_vertices * sizeof(vector3)); for (nv = 0; nv < num_vertices; nv++) { double cx; - double cy; - if (prsm->vertices_p.items[nv].x == 0) { + if (prsm->sidewall_angle == 0 ) { + cx = 1; + } + else if (prsm->vertices_p.items[nv].x == 0) { cx = 0; } else { cx = 1 - prsm->height / (prsm->vertices_p.items[nv].x * tan(theta)); } - if (prsm->vertices_p.items[nv].y == 0) { + + double cy; + if (prsm->sidewall_angle == 0 ) { + cy = 1; + } + else if (prsm->vertices_p.items[nv].y == 0) { cy = 0; } else { cy = 1 - prsm->height / (prsm->vertices_p.items[nv].y * tan(theta)); } + prsm->top_polygon_diff_vectors_p.items[nv].x = (cx - 1) * prsm->vertices_p.items[nv].x; prsm->top_polygon_diff_vectors_p.items[nv].y = (cy - 1) * prsm->vertices_p.items[nv].y; prsm->top_polygon_diff_vectors_p.items[nv].z = prsm->height - prsm->vertices_p.items[nv].z; From c9c742123bc3044198b5f94d12f3cee100c6791e Mon Sep 17 00:00:00 2001 From: danielwboyce Date: Sun, 12 Jan 2020 16:20:58 -0700 Subject: [PATCH 13/63] Correction to point_in_or_on_prism(). --- utils/geom.c | 6 +++++- 1 file changed, 5 insertions(+), 1 deletion(-) diff --git a/utils/geom.c b/utils/geom.c index be80112..b4a493c 100644 --- a/utils/geom.c +++ b/utils/geom.c @@ -2117,6 +2117,10 @@ boolean point_in_or_on_prism(prism *prsm, vector3 pc, boolean include_boundaries if (pp.z < 0.0 || pp.z > prsm->height) return 0; vector3 *nodes = prsm->vertices_p.items; int num_nodes = prsm->vertices_p.num_items; + int nv; + for (nv = 0; nv < num_nodes; nv++) { + nodes[nv] = vector3_plus(nodes[nv], vector3_scale(pp.z, prsm->top_polygon_diff_vectors_scaled_p.items[nv])); + } return node_in_or_on_polygon(pp, nodes, num_nodes, include_boundaries); } @@ -2575,7 +2579,7 @@ void init_prism(geometric_object *o) { prsm->top_polygon_diff_vectors_p.items[nv].x = (cx - 1) * prsm->vertices_p.items[nv].x; prsm->top_polygon_diff_vectors_p.items[nv].y = (cy - 1) * prsm->vertices_p.items[nv].y; - prsm->top_polygon_diff_vectors_p.items[nv].z = prsm->height - prsm->vertices_p.items[nv].z; + prsm->top_polygon_diff_vectors_p.items[nv].z = prsm->height; } prsm->top_polygon_diff_vectors_scaled_p.num_items = num_vertices; From 078b4761e003d479ba06e7c5e283225964b2591c Mon Sep 17 00:00:00 2001 From: danielwboyce Date: Mon, 13 Jan 2020 09:42:06 -0700 Subject: [PATCH 14/63] Update to prism2gnuplot() so that it will work with any sidewall angle --- utils/test-prism.c | 16 ++++++++++------ 1 file changed, 10 insertions(+), 6 deletions(-) diff --git a/utils/test-prism.c b/utils/test-prism.c index 4be289d..824f637 100644 --- a/utils/test-prism.c +++ b/utils/test-prism.c @@ -185,20 +185,24 @@ vector3 random_unit_vector3() { /* gnuplot> splot 'MyFile' u 1:2:3 w lp pt 7 ps 1 */ /***************************************************************/ void prism2gnuplot(prism *prsm, char *filename) { - vector3 *vertices = prsm->vertices_p.items; int num_vertices = prsm->vertices_p.num_items; double height = prsm->height; + vector3 *vertices_bottom = prsm->vertices_p.items; + vector3 *vertices_top = prsm->vertices_p.items; + int nv; + for (nv = 0; nv < num_vertices; nv++) { + vertices_top[nv] = vector3_plus(prsm->vertices_p.items[nv], prsm->top_polygon_diff_vectors_p.items[nv]); + } FILE *f = fopen(filename, "w"); - int nv; for (nv = 0; nv < num_vertices; nv++) { - vector3 vap = vertices[nv]; + vector3 vap = vertices_bottom[nv]; vap.z = 0.0; - vector3 vbp = vertices[nv]; + vector3 vbp = vertices_top[nv]; vbp.z = height; - vector3 vcp = vertices[(nv + 1) % num_vertices]; + vector3 vcp = vertices_bottom[(nv + 1) % num_vertices]; vcp.z = height; - vector3 vdp = vertices[(nv + 1) % num_vertices]; + vector3 vdp = vertices_top[(nv + 1) % num_vertices]; vdp.z = 0.0; vector3 vac = prism_coordinate_p2c(prsm, vap); vector3 vbc = prism_coordinate_p2c(prsm, vbp); From fcbfade3b3afe2fc8107ab6fadda39567d41107b Mon Sep 17 00:00:00 2001 From: danielwboyce Date: Mon, 13 Jan 2020 13:06:20 -0700 Subject: [PATCH 15/63] Updates for prism2gnuplot() --- utils/geom.c | 6 +++--- utils/test-prism.c | 31 +++++++++++++++++++------------ 2 files changed, 22 insertions(+), 15 deletions(-) diff --git a/utils/geom.c b/utils/geom.c index b4a493c..905a317 100644 --- a/utils/geom.c +++ b/utils/geom.c @@ -2550,12 +2550,12 @@ void init_prism(geometric_object *o) { if (isnan(prsm->sidewall_angle)) { prsm->sidewall_angle = 0.0; } - double theta = (K_PI/2) - prsm->sidewall_angle; + number theta = (K_PI/2) - prsm->sidewall_angle; prsm->top_polygon_diff_vectors_p.num_items = num_vertices; prsm->top_polygon_diff_vectors_p.items = (vector3 *)malloc(num_vertices * sizeof(vector3)); for (nv = 0; nv < num_vertices; nv++) { - double cx; + number cx; if (prsm->sidewall_angle == 0 ) { cx = 1; } @@ -2566,7 +2566,7 @@ void init_prism(geometric_object *o) { cx = 1 - prsm->height / (prsm->vertices_p.items[nv].x * tan(theta)); } - double cy; + number cy; if (prsm->sidewall_angle == 0 ) { cy = 1; } diff --git a/utils/test-prism.c b/utils/test-prism.c index 824f637..7ef417a 100644 --- a/utils/test-prism.c +++ b/utils/test-prism.c @@ -187,22 +187,27 @@ vector3 random_unit_vector3() { void prism2gnuplot(prism *prsm, char *filename) { int num_vertices = prsm->vertices_p.num_items; double height = prsm->height; - vector3 *vertices_bottom = prsm->vertices_p.items; - vector3 *vertices_top = prsm->vertices_p.items; + vector3_list vertices_bottom; + vertices_bottom.num_items = num_vertices; + vertices_bottom.items = (vector3 *)malloc(num_vertices * sizeof(vector3)); + memcpy(vertices_bottom.items, prsm->vertices_p.items, num_vertices * sizeof(vector3)); + vector3_list vertices_top; + vertices_top.num_items = num_vertices; + vertices_top.items = (vector3 *)malloc(num_vertices * sizeof(vector3)); int nv; for (nv = 0; nv < num_vertices; nv++) { - vertices_top[nv] = vector3_plus(prsm->vertices_p.items[nv], prsm->top_polygon_diff_vectors_p.items[nv]); + vertices_top.items[nv] = vector3_plus(prsm->vertices_p.items[nv], prsm->top_polygon_diff_vectors_p.items[nv]); } FILE *f = fopen(filename, "w"); for (nv = 0; nv < num_vertices; nv++) { - vector3 vap = vertices_bottom[nv]; + vector3 vap = vertices_bottom.items[nv]; vap.z = 0.0; - vector3 vbp = vertices_top[nv]; + vector3 vbp = vertices_top.items[nv]; vbp.z = height; - vector3 vcp = vertices_bottom[(nv + 1) % num_vertices]; + vector3 vcp = vertices_bottom.items[(nv + 1) % num_vertices]; vcp.z = height; - vector3 vdp = vertices_top[(nv + 1) % num_vertices]; + vector3 vdp = vertices_top.items[(nv + 1) % num_vertices]; vdp.z = 0.0; vector3 vac = prism_coordinate_p2c(prsm, vap); vector3 vbc = prism_coordinate_p2c(prsm, vbp); @@ -217,6 +222,8 @@ void prism2gnuplot(prism *prsm, char *filename) { fprintf(f, "\n\n"); } fclose(f); + + printf("prism2gnuplot was run!\n"); } /***************************************************************/ @@ -475,12 +482,12 @@ int test_sidewall_prisms_to_gnuplot() { geometric_object normal_sidewall_geom_object = make_prism(m, nodes, num_nodes, height, zhat, normal_sidewall); prism *normal_sidewall_prism = normal_sidewall_geom_object.subclass.prism_data; - double ten_degree_sidewall = 10.0 * 2 * K_PI / 360.0; + double ten_degree_sidewall = 1.0 * 2 * K_PI / 360.0; geometric_object ten_degree_sidewall_geom_object = make_prism(m, nodes, num_nodes, height, zhat, ten_degree_sidewall); - prism *ten_degree_sidewall_prism = normal_sidewall_geom_object.subclass.prism_data; + prism *ten_degree_sidewall_prism = ten_degree_sidewall_geom_object.subclass.prism_data; - prism2gnuplot(normal_sidewall_prism, "normal_sidewall_gnu_plot.dat"); - prism2gnuplot(ten_degree_sidewall_prism, "ten_degree_sidewall_gnu_plot.dat"); + prism2gnuplot(normal_sidewall_prism, "normal_sidewall_gnu_plot"); + prism2gnuplot(ten_degree_sidewall_prism, "ten_degree_sidewall_gnu_plot"); return 0; } @@ -547,7 +554,7 @@ int run_unit_tests() { int num_failed_4 = test_point_in_polygon(write_log); int num_failed_5 = test_sidewall_prisms_to_gnuplot(); - return num_failed_1 + num_failed_2 + num_failed_3 + num_failed_4; + return num_failed_1 + num_failed_2 + num_failed_3 + num_failed_4 + num_failed_5; } /***************************************************************/ From e83f33426970515e8e7b76b038af8c0d5890fc1c Mon Sep 17 00:00:00 2001 From: danielwboyce Date: Mon, 13 Jan 2020 13:47:41 -0700 Subject: [PATCH 16/63] Update to cx and cy calculations for accuracy --- utils/geom.c | 4 ++-- utils/test-prism.c | 8 ++++---- 2 files changed, 6 insertions(+), 6 deletions(-) diff --git a/utils/geom.c b/utils/geom.c index 905a317..eb10b0d 100644 --- a/utils/geom.c +++ b/utils/geom.c @@ -2563,7 +2563,7 @@ void init_prism(geometric_object *o) { cx = 0; } else { - cx = 1 - prsm->height / (prsm->vertices_p.items[nv].x * tan(theta)); + cx = 1 - prsm->height / (abs(prsm->vertices_p.items[nv].x) * tan(theta)); } number cy; @@ -2574,7 +2574,7 @@ void init_prism(geometric_object *o) { cy = 0; } else { - cy = 1 - prsm->height / (prsm->vertices_p.items[nv].y * tan(theta)); + cy = 1 - prsm->height / (abs(prsm->vertices_p.items[nv].y) * tan(theta)); } prsm->top_polygon_diff_vectors_p.items[nv].x = (cx - 1) * prsm->vertices_p.items[nv].x; diff --git a/utils/test-prism.c b/utils/test-prism.c index 7ef417a..9de85a1 100644 --- a/utils/test-prism.c +++ b/utils/test-prism.c @@ -470,10 +470,10 @@ int test_sidewall_prisms_to_gnuplot() { int num_nodes = 4; vector3 nodes[num_nodes]; - nodes[0] = make_vector3(1.0, 1.0, 0.0); - nodes[1] = make_vector3(1.0, -1.0, 0.0); - nodes[2] = make_vector3(-1.0, -1.0, 0.0); - nodes[3] = make_vector3(-1.0, 1.0, 0.0); + nodes[0] = make_vector3(-1.0, -1.0, 0.0); + nodes[1] = make_vector3(-1.0, 1.0, 0.0); + nodes[2] = make_vector3(1.0, 1.0, 0.0); + nodes[3] = make_vector3(1.0, -1.0, 0.0); double height = 10; vector3 zhat = make_vector3(0, 0, 1); From eb66a05c6c772e513689ce13715ae0724ea58b36 Mon Sep 17 00:00:00 2001 From: danielwboyce Date: Mon, 13 Jan 2020 15:15:39 -0700 Subject: [PATCH 17/63] Update to prism2gnuplot() --- utils/test-prism.c | 31 +++++++++++++++++++------------ 1 file changed, 19 insertions(+), 12 deletions(-) diff --git a/utils/test-prism.c b/utils/test-prism.c index 9de85a1..8efb9fa 100644 --- a/utils/test-prism.c +++ b/utils/test-prism.c @@ -205,20 +205,27 @@ void prism2gnuplot(prism *prsm, char *filename) { vap.z = 0.0; vector3 vbp = vertices_top.items[nv]; vbp.z = height; - vector3 vcp = vertices_bottom.items[(nv + 1) % num_vertices]; + vector3 vcp = vertices_top.items[(nv + 1) % num_vertices]; vcp.z = height; - vector3 vdp = vertices_top.items[(nv + 1) % num_vertices]; + vector3 vdp = vertices_bottom.items[(nv + 1) % num_vertices]; vdp.z = 0.0; vector3 vac = prism_coordinate_p2c(prsm, vap); vector3 vbc = prism_coordinate_p2c(prsm, vbp); vector3 vcc = prism_coordinate_p2c(prsm, vcp); vector3 vdc = prism_coordinate_p2c(prsm, vdp); - - fprintf(f, "%e %e %e %e %e %e \n", vac.x, vac.y, vac.z, vap.x, vap.y, vap.z); - fprintf(f, "%e %e %e %e %e %e \n", vbc.x, vbc.y, vbc.z, vbp.x, vbp.y, vbp.z); - fprintf(f, "%e %e %e %e %e %e \n", vcc.x, vcc.y, vcc.z, vcp.x, vcp.y, vcp.z); - fprintf(f, "%e %e %e %e %e %e \n", vdc.x, vdc.y, vdc.z, vdp.x, vdp.y, vdp.z); - fprintf(f, "%e %e %e %e %e %e \n", vac.x, vac.y, vac.z, vap.x, vap.y, vap.z); + /* + fprintf(f, "%e %e %e %e %e %e \n", vac.x, vac.y, vac.z, prsm->top_polygon_diff_vectors_p.items[nv].x, prsm->top_polygon_diff_vectors_p.items[nv].y, prsm->top_polygon_diff_vectors_p.items[nv].z); + fprintf(f, "%e %e %e %e %e %e \n", vbc.x, vbc.y, vbc.z, -1 * prsm->top_polygon_diff_vectors_p.items[nv].x, -1 * prsm->top_polygon_diff_vectors_p.items[nv].y, -1 * prsm->top_polygon_diff_vectors_p.items[nv].z); + fprintf(f, "%e %e %e %e %e %e \n", vcc.x, vcc.y, vcc.z, prsm->top_polygon_diff_vectors_p.items[(nv + 1) % num_vertices].x, prsm->top_polygon_diff_vectors_p.items[(nv + 1) % num_vertices].y, prsm->top_polygon_diff_vectors_p.items[(nv + 1) % num_vertices].z); + fprintf(f, "%e %e %e %e %e %e \n", vdc.x, vdc.y, vdc.z, -1 * prsm->top_polygon_diff_vectors_p.items[(nv + 1) % num_vertices].x, -1 * prsm->top_polygon_diff_vectors_p.items[(nv + 1) % num_vertices].y, -1 * prsm->top_polygon_diff_vectors_p.items[(nv + 1) % num_vertices].z); + fprintf(f, "%e %e %e %e %e %e \n", vac.x, vac.y, vac.z, prsm->top_polygon_diff_vectors_p.items[nv].x, prsm->top_polygon_diff_vectors_p.items[nv].y, prsm->top_polygon_diff_vectors_p.items[nv].z); + fprintf(f, "\n\n"); + */ + fprintf(f, "%e %e %e \n", vac.x, vac.y, vac.z); + fprintf(f, "%e %e %e \n", vbc.x, vbc.y, vbc.z); + fprintf(f, "%e %e %e \n", vcc.x, vcc.y, vcc.z); + fprintf(f, "%e %e %e \n", vdc.x, vdc.y, vdc.z); + fprintf(f, "%e %e %e \n", vac.x, vac.y, vac.z); fprintf(f, "\n\n"); } fclose(f); @@ -482,12 +489,12 @@ int test_sidewall_prisms_to_gnuplot() { geometric_object normal_sidewall_geom_object = make_prism(m, nodes, num_nodes, height, zhat, normal_sidewall); prism *normal_sidewall_prism = normal_sidewall_geom_object.subclass.prism_data; - double ten_degree_sidewall = 1.0 * 2 * K_PI / 360.0; - geometric_object ten_degree_sidewall_geom_object = make_prism(m, nodes, num_nodes, height, zhat, ten_degree_sidewall); - prism *ten_degree_sidewall_prism = ten_degree_sidewall_geom_object.subclass.prism_data; + double one_degree_sidewall = 1.0 * 2 * K_PI / 360.0; + geometric_object one_degree_sidewall_geom_object = make_prism(m, nodes, num_nodes, height, zhat, one_degree_sidewall); + prism *one_degree_sidewall_prism = one_degree_sidewall_geom_object.subclass.prism_data; prism2gnuplot(normal_sidewall_prism, "normal_sidewall_gnu_plot"); - prism2gnuplot(ten_degree_sidewall_prism, "ten_degree_sidewall_gnu_plot"); + prism2gnuplot(one_degree_sidewall_prism, "one_degree_sidewall_gnu_plot"); return 0; } From f17fc40268fcc635aaddc85bf7b8241e458d2b3d Mon Sep 17 00:00:00 2001 From: danielwboyce Date: Tue, 14 Jan 2020 13:45:16 -0700 Subject: [PATCH 18/63] * Changed vertices to vertices_bottom and vertices_p to vertices_bottom_p. * Added derived quantities vertices_top and vertices_top_p to prism subclass (calculations to derive these quantities have not yet been added). * Misc. changes to update functions to work better with top polygon/bottom polygon framework. --- utils/ctlgeom.h | 4 +- utils/geom.c | 103 +++++++++++++++++++++++---------------------- utils/geom.scm | 10 +++-- utils/test-prism.c | 93 +++++++++++++++++++--------------------- 4 files changed, 104 insertions(+), 106 deletions(-) diff --git a/utils/ctlgeom.h b/utils/ctlgeom.h index b9145e9..eb20e20 100644 --- a/utils/ctlgeom.h +++ b/utils/ctlgeom.h @@ -156,12 +156,12 @@ extern boolean node_in_or_on_polygon(vector3 q0, vector3 *nodes, int num_nodes, boolean include_boundaries); // prism with `center` field computed automatically from vertices, height, axis -GEOMETRIC_OBJECT make_prism(MATERIAL_TYPE material, const vector3 *vertices, int num_vertices, +GEOMETRIC_OBJECT make_prism(MATERIAL_TYPE material, const vector3 *vertices_bottom, int num_vertices, double height, vector3 axis, double sidewall_angle); // as make_prism, but with a rigid translation so that the prism is centered at center GEOMETRIC_OBJECT make_prism_with_center(MATERIAL_TYPE material, vector3 center, - const vector3 *vertices, int num_vertices, double height, + const vector3 *vertices_bottom, int num_vertices, double height, vector3 axis, double sidewall_angle); int vector3_nearly_equal(vector3 v1, vector3 v2, double tolerance); diff --git a/utils/geom.c b/utils/geom.c index eb10b0d..bd05d7d 100644 --- a/utils/geom.c +++ b/utils/geom.c @@ -914,13 +914,13 @@ double geom_object_volume(GEOMETRIC_OBJECT o) { } case GEOM PRISM: { // needs updating for non-normal sidewalls - vector3_list vertices = o.subclass.prism_data->vertices_p; + vector3_list vertices_bottom = o.subclass.prism_data->vertices_bottom_p; double area = 0; int i; - for (i = 0; i < vertices.num_items; ++i) { - int i1 = (i + 1) % vertices.num_items; - area += 0.5 * (vertices.items[i1].x - vertices.items[i].x) * - (vertices.items[i1].y + vertices.items[i].y); + for (i = 0; i < vertices_bottom.num_items; ++i) { + int i1 = (i + 1) % vertices_bottom.num_items; + area += 0.5 * (vertices_bottom.items[i1].x - vertices_bottom.items[i].x) * + (vertices_bottom.items[i1].y + vertices_bottom.items[i].y); } return fabs(area) * o.subclass.prism_data->height; } @@ -2115,11 +2115,12 @@ boolean point_in_or_on_prism(prism *prsm, vector3 pc, boolean include_boundaries double height = prsm->height; vector3 pp = prism_coordinate_c2p(prsm, pc); if (pp.z < 0.0 || pp.z > prsm->height) return 0; - vector3 *nodes = prsm->vertices_p.items; - int num_nodes = prsm->vertices_p.num_items; + // needs to be updated so that vertices_bottom_p.items isn't contaminated + int num_nodes = prsm->vertices_bottom_p.num_items; + vector3 nodes[num_nodes]; int nv; for (nv = 0; nv < num_nodes; nv++) { - nodes[nv] = vector3_plus(nodes[nv], vector3_scale(pp.z, prsm->top_polygon_diff_vectors_scaled_p.items[nv])); + nodes[nv] = vector3_plus(prsm->vertices_bottom_p.items[nv], vector3_scale(pp.z, prsm->top_polygon_diff_vectors_scaled_p.items[nv])); } return node_in_or_on_polygon(pp, nodes, num_nodes, include_boundaries); } @@ -2155,8 +2156,8 @@ static int dcmp(const void *pd1, const void *pd2) { int intersect_line_with_prism(prism *prsm, vector3 pc, vector3 dc, double *slist) { vector3 pp = prism_coordinate_c2p(prsm, pc); vector3 dp = prism_vector_c2p(prsm, dc); - vector3 *vps = prsm->vertices_p.items; - int num_vertices = prsm->vertices_p.num_items; + vector3 *vps = prsm->vertices_bottom_p.items; + int num_vertices = prsm->vertices_bottom_p.num_items; double height = prsm->height; // use length of first polygon edge as a length scale for judging @@ -2301,8 +2302,8 @@ double min_distance_to_quadrilateral(vector3 p, vector3 o, vector3 v1, vector3 v // fc==0/1 for floor/ceiling double min_distance_to_prism_roof_or_ceiling(vector3 pp, prism *prsm, int fc) { - vector3 *vps = prsm->vertices_p.items; - int num_vertices = prsm->vertices_p.num_items; + vector3 *vps = prsm->vertices_bottom_p.items; + int num_vertices = prsm->vertices_bottom_p.num_items; vector3 op = {0.0, 0.0, 0.0}; if (fc == 1) op.z = prsm->height; // origin of floor/ceiling vector3 zhatp = {0, 0, 1.0}; @@ -2327,8 +2328,8 @@ vector3 normal_to_prism(prism *prsm, vector3 pc) { if (prsm->height == 0.0) return prsm->axis; double height = prsm->height; - vector3 *vps = prsm->vertices_p.items; - int num_vertices = prsm->vertices_p.num_items; + vector3 *vps_bottom = prsm->vertices_bottom_p.items; + int num_vertices = prsm->vertices_bottom_p.num_items; vector3 zhatp = {0.0, 0.0, 1.0}; vector3 axisp = vector3_scale(height, zhatp); @@ -2340,10 +2341,12 @@ vector3 normal_to_prism(prism *prsm, vector3 pc) { // consider side walls for (nv = 0; nv < num_vertices; nv++) { int nvp1 = (nv == (num_vertices - 1) ? 0 : nv + 1); - vector3 v0p = vps[nv]; - vector3 v1p = vector3_minus(vps[nvp1], vps[nv]); + vector3 v0p = vps_bottom[nv]; + vector3 v1p = vector3_minus(vps_bottom[nvp1], vps_bottom[nv]); + // v2p needs to be changed to be from v0p to the corresponding vertex in the top polygon vector3 v2p = axisp; vector3 v3p = unit_vector3(vector3_cross(v1p, v2p)); + // quadrilateral determined {v0p, v0p+v1p, v0p+v2p, v0p+v1p+v2p} with normal vector v3p double s = min_distance_to_quadrilateral(pp, v0p, v1p, v2p, v3p); if (fabs(s) < min_distance) { min_distance = fabs(s); @@ -2366,14 +2369,14 @@ vector3 normal_to_prism(prism *prsm, vector3 pc) { /***************************************************************/ /***************************************************************/ void get_prism_bounding_box(prism *prsm, geom_box *box) { - vector3 *vertices = prsm->vertices.items; - int num_vertices = prsm->vertices.num_items; - box->low = box->high = vertices[0]; + vector3 *vertices_bottom = prsm->vertices_bottom.items; + int num_vertices = prsm->vertices_bottom.num_items; + box->low = box->high = vertices_bottom[0]; int nv, fc; for (nv = 0; nv < num_vertices; nv++) for (fc = 0; fc < 2; fc++) // 'floor,ceiling' { - vector3 v = vertices[nv]; + vector3 v = vertices_bottom[nv]; if (fc == 1) v = vector3_plus(v, vector3_scale(prsm->height, prsm->axis)); box->low.x = fmin(box->low.x, v.x); @@ -2392,8 +2395,8 @@ void get_prism_bounding_box(prism *prsm, geom_box *box) { void display_prism_info(int indentby, geometric_object *o) { prism *prsm = o->subclass.prism_data; - vector3 *vs = prsm->vertices.items; - int num_vertices = prsm->vertices.num_items; + vector3 *vs = prsm->vertices_bottom.items; + int num_vertices = prsm->vertices_bottom.num_items; ctl_printf("%*s height %g, axis (%g,%g,%g), sidewall angle: %g radians, %i vertices:\n", indentby, "", prsm->height, prsm->axis.x, prsm->axis.y, prsm->axis.z, prsm->sidewall_angle, num_vertices); @@ -2436,15 +2439,15 @@ vector3 triangle_normal(vector3 v1, vector3 v2, vector3 v3) { vector3 auto_center = {NAN, NAN, NAN}; void init_prism(geometric_object *o) { prism *prsm = o->subclass.prism_data; - vector3 *vertices = prsm->vertices.items; - int num_vertices = prsm->vertices.num_items; + vector3 *vertices_bottom = prsm->vertices_bottom.items; + int num_vertices = prsm->vertices_bottom.num_items; CHECK(num_vertices >= 3, "fewer than 3 vertices in init_prism"); // compute centroid of vertices vector3 centroid = {0.0, 0.0, 0.0}; int nv; for (nv = 0; nv < num_vertices; nv++) - centroid = vector3_plus(centroid, vertices[nv]); + centroid = vector3_plus(centroid, vertices_bottom[nv]); prsm->centroid = centroid = vector3_scale(1.0 / ((double)num_vertices), centroid); // make sure all vertices lie in a plane, i.e. that the normal @@ -2454,7 +2457,7 @@ void init_prism(geometric_object *o) { double tol = 1.0e-6; for (nv = 0; nv < num_vertices; nv++) { int nvp1 = (nv + 1) % num_vertices; - vector3 tri_normal = triangle_normal(centroid, vertices[nv], vertices[nvp1]); + vector3 tri_normal = triangle_normal(centroid, vertices_bottom[nv], vertices_bottom[nvp1]); if (vector3_norm(tri_normal) == 0.0) // vertices collinear with centroid continue; if (!plane_normal_set) { @@ -2493,7 +2496,7 @@ void init_prism(geometric_object *o) { else { vector3 shift = vector3_minus(o->center, current_center); for (nv = 0; nv < num_vertices; nv++) - vertices[nv] = vector3_plus(vertices[nv], shift); + vertices_bottom[nv] = vector3_plus(vertices_bottom[nv], shift); centroid = vector3_plus(centroid, shift); } @@ -2522,31 +2525,31 @@ void init_prism(geometric_object *o) { yhat = y0hat; } else { - xhat = unit_vector3(vector3_minus(vertices[1], vertices[0])); + xhat = unit_vector3(vector3_minus(vertices_bottom[1], vertices_bottom[0])); yhat = unit_vector3(vector3_cross(zhat, xhat)); } matrix3x3 m_p2c = {xhat, yhat, zhat}; prsm->m_p2c = m_p2c; prsm->m_c2p = matrix3x3_inverse(m_p2c); - // compute vertices in prism coordinate system - prsm->vertices_p.num_items = num_vertices; - prsm->vertices_p.items = (vector3 *)malloc(num_vertices * sizeof(vector3)); + // compute vertices_bottom in prism coordinate system + prsm->vertices_bottom_p.num_items = num_vertices; + prsm->vertices_bottom_p.items = (vector3 *)malloc(num_vertices * sizeof(vector3)); for (nv = 0; nv < num_vertices; nv++) - prsm->vertices_p.items[nv] = prism_coordinate_c2p(prsm, vertices[nv]); + prsm->vertices_bottom_p.items[nv] = prism_coordinate_c2p(prsm, vertices_bottom[nv]); // calculate difference vectors between bottom polygon and the top polygon, where // * the bottom polygon is the one passed in to the the make_prism() function, - // stored in vertices and vertices_p + // stored in vertices_bottom and vertices_bottom_p // * the top polygon is the top surface (parallel to the bottom polygon) resulting // from the extrusion of the bottom polygon. Whether or not the extrusion tapers // is dependent on the value of sidewall_angle. // ** The value of each of the top polygon vertices can be found - // vertices_p + top_polygon_diff_vectors_p - // vertices + top_polygon_diff_vectors + // vertices_bottom_p + top_polygon_diff_vectors_p + // vertices_bottom + top_polygon_diff_vectors // ** A linearly interpolated value of the polygon vertices between the bottom // polygon and the top can be found - // vertices_p + top_polygon_diff_vectors_scaled_p * z + // vertices_bottom_p + top_polygon_diff_vectors_scaled_p * z if (isnan(prsm->sidewall_angle)) { prsm->sidewall_angle = 0.0; } @@ -2559,26 +2562,26 @@ void init_prism(geometric_object *o) { if (prsm->sidewall_angle == 0 ) { cx = 1; } - else if (prsm->vertices_p.items[nv].x == 0) { + else if (prsm->vertices_bottom_p.items[nv].x == 0) { cx = 0; } else { - cx = 1 - prsm->height / (abs(prsm->vertices_p.items[nv].x) * tan(theta)); + cx = 1 - prsm->height / (abs(prsm->vertices_bottom_p.items[nv].x) * tan(theta)); } number cy; if (prsm->sidewall_angle == 0 ) { cy = 1; } - else if (prsm->vertices_p.items[nv].y == 0) { + else if (prsm->vertices_bottom_p.items[nv].y == 0) { cy = 0; } else { - cy = 1 - prsm->height / (abs(prsm->vertices_p.items[nv].y) * tan(theta)); + cy = 1 - prsm->height / (abs(prsm->vertices_bottom_p.items[nv].y) * tan(theta)); } - prsm->top_polygon_diff_vectors_p.items[nv].x = (cx - 1) * prsm->vertices_p.items[nv].x; - prsm->top_polygon_diff_vectors_p.items[nv].y = (cy - 1) * prsm->vertices_p.items[nv].y; + prsm->top_polygon_diff_vectors_p.items[nv].x = (cx - 1) * prsm->vertices_bottom_p.items[nv].x; + prsm->top_polygon_diff_vectors_p.items[nv].y = (cy - 1) * prsm->vertices_bottom_p.items[nv].y; prsm->top_polygon_diff_vectors_p.items[nv].z = prsm->height; } @@ -2609,25 +2612,25 @@ void init_prism(geometric_object *o) { /***************************************************************/ /* routines called from C++ or python codes to create prisms */ /***************************************************************/ -// prism with center determined automatically from vertices, height, and axis -geometric_object make_prism(material_type material, const vector3 *vertices, int num_vertices, +// prism with center determined automatically from vertices_bottom, height, and axis +geometric_object make_prism(material_type material, const vector3 *vertices_bottom, int num_vertices, double height, vector3 axis, double sidewall_angle) { - return make_prism_with_center(material, auto_center, vertices, num_vertices, height, axis, + return make_prism_with_center(material, auto_center, vertices_bottom, num_vertices, height, axis, sidewall_angle); } // prism in which all vertices are translated to ensure that the prism is centered at center geometric_object make_prism_with_center(material_type material, vector3 center, - const vector3 *vertices, int num_vertices, double height, + const vector3 *vertices_bottom, int num_vertices, double height, vector3 axis, double sidewall_angle) { geometric_object o = make_geometric_object(material, center); o.which_subclass = GEOM PRISM; prism *prsm = o.subclass.prism_data = MALLOC1(prism); CHECK(prsm, "out of memory"); - prsm->vertices.num_items = num_vertices; - prsm->vertices.items = (vector3 *)malloc(num_vertices * sizeof(vector3)); - CHECK(prsm->vertices.items, "out of memory"); - memcpy(prsm->vertices.items, vertices, num_vertices * sizeof(vector3)); + prsm->vertices_bottom.num_items = num_vertices; + prsm->vertices_bottom.items = (vector3 *)malloc(num_vertices * sizeof(vector3)); + CHECK(prsm->vertices_bottom.items, "out of memory"); + memcpy(prsm->vertices_bottom.items, vertices_bottom, num_vertices * sizeof(vector3)); prsm->height = height; prsm->axis = axis; prsm->sidewall_angle = sidewall_angle; diff --git a/utils/geom.scm b/utils/geom.scm index 17571d5..5620d92 100644 --- a/utils/geom.scm +++ b/utils/geom.scm @@ -124,16 +124,18 @@ ; a foundry that cannot grow objects with a perfectly normal sidewall. (define-class prism geometric-object ; fields to be filled in by users - (define-property vertices '() (make-list-type 'vector3)) + (define-property vertices_bottom '() (make-list-type 'vector3)) (define-property height 0 'number) (define-property axis (vector3 0 0 0) 'vector3) (define-property sidewall_angle 0 'number) ; derived fields computed internally - (define-property vertices_p '() (make-list-type 'vector3)) - (define-property top_polygon_diff_vectors '() (make-list-type 'vector3)) - (define-property top_polygon_diff_vectors_scaled '() (make-list-type 'vector3)) + (define-property vertices_bottom_p '() (make-list-type 'vector3)) (define-property top_polygon_diff_vectors_p '() (make-list-type 'vector3)) (define-property top_polygon_diff_vectors_scaled_p '() (make-list-type 'vector3)) + (define-property vertices_top_p '() (make-list-type 'vector3)) + (define-property top_polygon_diff_vectors '() (make-list-type 'vector3)) + (define-property top_polygon_diff_vectors_scaled '() (make-list-type 'vector3)) + (define-property vertices_top '() (make-list-type 'vector3)) (define-property centroid (vector3 0 0 0) 'vector3) (define-property workspace '() (make-list-type 'number)) (define-property m_c2p identity_matrix 'matrix3x3) diff --git a/utils/test-prism.c b/utils/test-prism.c index 8efb9fa..b99cea3 100644 --- a/utils/test-prism.c +++ b/utils/test-prism.c @@ -79,16 +79,16 @@ void GPQuad(FILE *f, vector3 v, vector3 l1, vector3 l2, prism *prsm) { /***************************************************************/ /***************************************************************/ void my_get_prism_bounding_box(prism *prsm, geom_box *box) { - vector3 *vertices = prsm->vertices_p.items; - int num_vertices = prsm->vertices_p.num_items; + vector3 *vertices_bottom = prsm->vertices_bottom_p.items; + int num_vertices = prsm->vertices_bottom_p.num_items; double height = prsm->height; - box->low = box->high = prism_coordinate_p2c(prsm, vertices[0]); + box->low = box->high = prism_coordinate_p2c(prsm, vertices_bottom[0]); int nv, fc; for (nv = 0; nv < num_vertices; nv++) for (fc = 0; fc < 2; fc++) // 'floor,ceiling' { - vector3 vp = vertices[nv]; + vector3 vp = vertices_bottom[nv]; if (fc == 1) vp.z = height; vector3 vc = prism_coordinate_p2c(prsm, vp); @@ -129,13 +129,15 @@ vector3 random_point_in_box(vector3 min_corner, vector3 max_corner) { /* random point uniformly distributed over a planar polygon */ /* (all z coordinates are 0) */ /************************************************************************/ -vector3 random_point_in_polygon(vector3 *vertices, int num_vertices) { +vector3 random_point_in_polygon(prsm *prsm) { // randomly choose a vertex and generate random point within the triangle // formed by that vertex, the next vertex, and the centroid + vector3 *vertices_bottom = prsm->vertices_bottom.items; + int num_vertices = prsm->vertices_bottom_num_items; int which_vertex = rand() % num_vertices; vector3 v0 = {0, 0, 0}; - vector3 v1 = vertices[which_vertex]; - vector3 v2 = vertices[(which_vertex + 1) % num_vertices]; + vector3 v1 = vertices_bottom[which_vertex]; + vector3 v2 = vertices_bottom[(which_vertex + 1) % num_vertices]; double xi = urand(0.0, 1.0), eta = urand(0.0, 1.0 - xi); return vector3_plus(vector3_scale(xi, vector3_minus(v1, v0)), vector3_scale(eta, vector3_minus(v2, v0))); @@ -146,8 +148,8 @@ vector3 random_point_in_polygon(vector3 *vertices, int num_vertices) { /************************************************************************/ vector3 random_point_on_prism(geometric_object o) { prism *prsm = o.subclass.prism_data; - vector3 *vertices = prsm->vertices_p.items; - int num_vertices = prsm->vertices_p.num_items; + vector3 *vertices_bottom = prsm->vertices_bottom_p.items; + int num_vertices = prsm->vertices_bottom_p.num_items; double height = prsm->height; // choose a face @@ -155,15 +157,15 @@ vector3 random_point_on_prism(geometric_object o) { int which_face = rand() % num_faces; if (which_face < num_vertices) // side face { - vector3 min_corner = vertices[which_face]; - vector3 max_corner = vertices[(which_face + 1) % num_vertices]; + vector3 min_corner = vertices_bottom[which_face]; + vector3 max_corner = vertices_bottom[(which_face + 1) % num_vertices]; max_corner.z = height; return random_point_in_box(prism_coordinate_p2c(prsm, min_corner), prism_coordinate_p2c(prsm, max_corner)); } else // floor or ceiling { - vector3 p = random_point_in_polygon(vertices, num_vertices); + vector3 p = random_point_in_polygon(prsm); if (which_face == num_faces - 1) p.z = height; return prism_coordinate_p2c(prsm, p); } @@ -185,18 +187,18 @@ vector3 random_unit_vector3() { /* gnuplot> splot 'MyFile' u 1:2:3 w lp pt 7 ps 1 */ /***************************************************************/ void prism2gnuplot(prism *prsm, char *filename) { - int num_vertices = prsm->vertices_p.num_items; + int num_vertices = prsm->vertices_bottom_p.num_items; double height = prsm->height; vector3_list vertices_bottom; vertices_bottom.num_items = num_vertices; vertices_bottom.items = (vector3 *)malloc(num_vertices * sizeof(vector3)); - memcpy(vertices_bottom.items, prsm->vertices_p.items, num_vertices * sizeof(vector3)); + memcpy(vertices_bottom.items, prsm->vertices_bottom_p.items, num_vertices * sizeof(vector3)); vector3_list vertices_top; vertices_top.num_items = num_vertices; vertices_top.items = (vector3 *)malloc(num_vertices * sizeof(vector3)); int nv; for (nv = 0; nv < num_vertices; nv++) { - vertices_top.items[nv] = vector3_plus(prsm->vertices_p.items[nv], prsm->top_polygon_diff_vectors_p.items[nv]); + vertices_top.items[nv] = vector3_plus(prsm->vertices_bottom_p.items[nv], prsm->top_polygon_diff_vectors_p.items[nv]); } FILE *f = fopen(filename, "w"); @@ -213,14 +215,7 @@ void prism2gnuplot(prism *prsm, char *filename) { vector3 vbc = prism_coordinate_p2c(prsm, vbp); vector3 vcc = prism_coordinate_p2c(prsm, vcp); vector3 vdc = prism_coordinate_p2c(prsm, vdp); - /* - fprintf(f, "%e %e %e %e %e %e \n", vac.x, vac.y, vac.z, prsm->top_polygon_diff_vectors_p.items[nv].x, prsm->top_polygon_diff_vectors_p.items[nv].y, prsm->top_polygon_diff_vectors_p.items[nv].z); - fprintf(f, "%e %e %e %e %e %e \n", vbc.x, vbc.y, vbc.z, -1 * prsm->top_polygon_diff_vectors_p.items[nv].x, -1 * prsm->top_polygon_diff_vectors_p.items[nv].y, -1 * prsm->top_polygon_diff_vectors_p.items[nv].z); - fprintf(f, "%e %e %e %e %e %e \n", vcc.x, vcc.y, vcc.z, prsm->top_polygon_diff_vectors_p.items[(nv + 1) % num_vertices].x, prsm->top_polygon_diff_vectors_p.items[(nv + 1) % num_vertices].y, prsm->top_polygon_diff_vectors_p.items[(nv + 1) % num_vertices].z); - fprintf(f, "%e %e %e %e %e %e \n", vdc.x, vdc.y, vdc.z, -1 * prsm->top_polygon_diff_vectors_p.items[(nv + 1) % num_vertices].x, -1 * prsm->top_polygon_diff_vectors_p.items[(nv + 1) % num_vertices].y, -1 * prsm->top_polygon_diff_vectors_p.items[(nv + 1) % num_vertices].z); - fprintf(f, "%e %e %e %e %e %e \n", vac.x, vac.y, vac.z, prsm->top_polygon_diff_vectors_p.items[nv].x, prsm->top_polygon_diff_vectors_p.items[nv].y, prsm->top_polygon_diff_vectors_p.items[nv].z); - fprintf(f, "\n\n"); - */ + fprintf(f, "%e %e %e \n", vac.x, vac.y, vac.z); fprintf(f, "%e %e %e \n", vbc.x, vbc.y, vbc.z); fprintf(f, "%e %e %e \n", vcc.x, vcc.y, vcc.z); @@ -229,16 +224,14 @@ void prism2gnuplot(prism *prsm, char *filename) { fprintf(f, "\n\n"); } fclose(f); - - printf("prism2gnuplot was run!\n"); } /***************************************************************/ /* write prism vertices and edges to GMSH geometry (.geo) file */ /***************************************************************/ void prism2gmsh(prism *prsm, char *filename) { - vector3 *vertices = prsm->vertices_p.items; - int num_vertices = prsm->vertices_p.num_items; + vector3 *vertices_bottom = prsm->vertices_bottom_p.items; + int num_vertices = prsm->vertices_bottom_p.num_items; double height = prsm->height; vector3 zhat = prsm->m_p2c.c2; vector3 axis = vector3_scale(height, zhat); @@ -246,7 +239,7 @@ void prism2gmsh(prism *prsm, char *filename) { FILE *f = fopen(filename, "w"); int nv; for (nv = 0; nv < num_vertices; nv++) { - vector3 vp = vertices[nv]; + vector3 vp = vertices_bottom[nv]; vector3 vc = prism_coordinate_p2c(prsm, vp); fprintf(f, "Point(%i)={%e, %e, %e};\n", nv, vc.x, vc.y, vc.z); } @@ -473,30 +466,30 @@ int test_point_in_polygon(int write_log) { /* separate GNU plot files */ /************************************************************************/ int test_sidewall_prisms_to_gnuplot() { - void *m = NULL; + void *m = NULL; - int num_nodes = 4; - vector3 nodes[num_nodes]; - nodes[0] = make_vector3(-1.0, -1.0, 0.0); - nodes[1] = make_vector3(-1.0, 1.0, 0.0); - nodes[2] = make_vector3(1.0, 1.0, 0.0); - nodes[3] = make_vector3(1.0, -1.0, 0.0); + int num_nodes = 4; + vector3 nodes[num_nodes]; + nodes[0] = make_vector3(-1.0, -1.0, 0.0); + nodes[1] = make_vector3(-1.0, 1.0, 0.0); + nodes[2] = make_vector3(1.0, 1.0, 0.0); + nodes[3] = make_vector3(1.0, -1.0, 0.0); - double height = 10; - vector3 zhat = make_vector3(0, 0, 1); + double height = 10; + vector3 zhat = make_vector3(0, 0, 1); - double normal_sidewall = 0; - geometric_object normal_sidewall_geom_object = make_prism(m, nodes, num_nodes, height, zhat, normal_sidewall); - prism *normal_sidewall_prism = normal_sidewall_geom_object.subclass.prism_data; + double normal_sidewall = 0; + geometric_object normal_sidewall_geom_object = make_prism(m, nodes, num_nodes, height, zhat, normal_sidewall); + prism *normal_sidewall_prism = normal_sidewall_geom_object.subclass.prism_data; - double one_degree_sidewall = 1.0 * 2 * K_PI / 360.0; - geometric_object one_degree_sidewall_geom_object = make_prism(m, nodes, num_nodes, height, zhat, one_degree_sidewall); - prism *one_degree_sidewall_prism = one_degree_sidewall_geom_object.subclass.prism_data; + double one_degree_sidewall = 1.0 * 2 * K_PI / 360.0; + geometric_object one_degree_sidewall_geom_object = make_prism(m, nodes, num_nodes, height, zhat, one_degree_sidewall); + prism *one_degree_sidewall_prism = one_degree_sidewall_geom_object.subclass.prism_data; - prism2gnuplot(normal_sidewall_prism, "normal_sidewall_gnu_plot"); - prism2gnuplot(one_degree_sidewall_prism, "one_degree_sidewall_gnu_plot"); + prism2gnuplot(normal_sidewall_prism, "normal_sidewall_gnu_plot.dat"); + prism2gnuplot(one_degree_sidewall_prism, "one_degree_sidewall_gnu_plot.dat"); - return 0; + return 0; } /***************************************************************/ @@ -657,7 +650,7 @@ int main(int argc, char *argv[]) { /***************************************************************/ /* read vertices from vertex file and create prism *************/ /***************************************************************/ - vector3 *vertices = 0; + vector3 *vertices_bottom = 0; int num_vertices = 0; FILE *f = fopen(vertexfile, "r"); if (!f) usage("could not open vertexfile"); @@ -671,12 +664,12 @@ int main(int argc, char *argv[]) { fprintf(stderr, "bad vertex on line %i of %s", num_vertices, vertexfile); exit(1); } - vertices = (vector3 *)realloc(vertices, num_vertices * sizeof(vector3)); - vertices[num_vertices - 1] = v; + vertices_bottom = (vector3 *)realloc(vertices, num_vertices * sizeof(vector3)); + vertices_bottom[num_vertices - 1] = v; } fclose(f); - geometric_object the_prism = make_prism(NULL, vertices, num_vertices, height, axis, 0.0); + geometric_object the_prism = make_prism(NULL, vertices_bottom, num_vertices, height, axis, 0.0); prism *prsm = the_prism.subclass.prism_data; prism2gmsh(prsm, "test-prism.pp"); prism2gnuplot(prsm, "test-prism.gp"); From be2b578a7d3a9329bee8fb0d84a02c2af6b7ada2 Mon Sep 17 00:00:00 2001 From: danielwboyce Date: Tue, 14 Jan 2020 14:12:57 -0700 Subject: [PATCH 19/63] Changes to some comments for unity. --- utils/ctlgeom.h | 2 +- utils/geom.c | 27 +++++++++++++++------------ utils/geom.scm | 14 +++++++------- 3 files changed, 23 insertions(+), 20 deletions(-) diff --git a/utils/ctlgeom.h b/utils/ctlgeom.h index eb20e20..0a8c204 100644 --- a/utils/ctlgeom.h +++ b/utils/ctlgeom.h @@ -155,7 +155,7 @@ GEOMETRIC_OBJECT make_ellipsoid(MATERIAL_TYPE material, vector3 center, vector3 extern boolean node_in_or_on_polygon(vector3 q0, vector3 *nodes, int num_nodes, boolean include_boundaries); -// prism with `center` field computed automatically from vertices, height, axis +// prism with `center` field computed automatically from bottom vertices, height, axis, sidewall angle GEOMETRIC_OBJECT make_prism(MATERIAL_TYPE material, const vector3 *vertices_bottom, int num_vertices, double height, vector3 axis, double sidewall_angle); diff --git a/utils/geom.c b/utils/geom.c index bd05d7d..eaaedc9 100644 --- a/utils/geom.c +++ b/utils/geom.c @@ -1904,8 +1904,10 @@ geometric_object make_ellipsoid(material_type material, vector3 center, vector3 /*************************************************************** * The remainder of this file implements geometric primitives for prisms. * A prism is a planar polygon, consisting of 3 or more user-specified - * vertices, extruded through a given thickness (the "height") in the - * direction of a given unit vector (the "axis.") + * vertices (the "bottom_vertices), extruded through a given thickness + * (the "height") in the direction of a given unit vector (the "axis") + * with the walls of the extrusion tapering at a given angle angle + * (the "sidewall_angle). * Most calculations are done in the "prism coordinate system", * in which the prism floor lies in the XY plane with centroid * at the origin and the prism axis is the positive Z-axis. @@ -2115,7 +2117,6 @@ boolean point_in_or_on_prism(prism *prsm, vector3 pc, boolean include_boundaries double height = prsm->height; vector3 pp = prism_coordinate_c2p(prsm, pc); if (pp.z < 0.0 || pp.z > prsm->height) return 0; - // needs to be updated so that vertices_bottom_p.items isn't contaminated int num_nodes = prsm->vertices_bottom_p.num_items; vector3 nodes[num_nodes]; int nv; @@ -2426,14 +2427,15 @@ vector3 triangle_normal(vector3 v1, vector3 v2, vector3 v3) { /***************************************************************/ /* On entry, the only fields in o->prism that are assumed to */ -/* be initialized are: vertices, height, and (optionally) axis.*/ -/* If axis has not been initialized (i.e. it is set to its */ -/* default value, which is the zero vector) then the prism axis*/ -/* is automatically computed as the normal to the vertex plane.*/ -/* If o->center is equal to auto_center on entry, then it is */ -/* set to the prism center, as computed from the vertices, */ -/* axis, and height. Otherwise, the prism is rigidly translated*/ -/* to center it at the specified value of o->center. */ +/* be initialized are: vertices_bottom, height, (optionally) */ +/* axis, and sidewall_angle. If axis has not been initialized */ +/* (i.e. it is set to its default value, which is the zero */ +/* vector) then the prism axis is automatically computed as */ +/* the normal to the vertex plane. If o->center is equal to */ +/* auto_center on entry, then it is set to the prism center, */ +/* as computed from the vertices, axis, and height. Otherwise, */ +/* the prism is rigidly translated to center it at the */ +/* specified value of o->center. */ /***************************************************************/ // special vector3 that signifies 'no value specified' vector3 auto_center = {NAN, NAN, NAN}; @@ -2612,7 +2614,8 @@ void init_prism(geometric_object *o) { /***************************************************************/ /* routines called from C++ or python codes to create prisms */ /***************************************************************/ -// prism with center determined automatically from vertices_bottom, height, and axis +// prism with center determined automatically from vertices_bottom, +// height, axis, and sidewall_angle geometric_object make_prism(material_type material, const vector3 *vertices_bottom, int num_vertices, double height, vector3 axis, double sidewall_angle) { return make_prism_with_center(material, auto_center, vertices_bottom, num_vertices, height, axis, diff --git a/utils/geom.scm b/utils/geom.scm index 5620d92..3f61809 100644 --- a/utils/geom.scm +++ b/utils/geom.scm @@ -92,13 +92,13 @@ ; some notes regarding prisms: ; (a) When instantiating a prism, typically only the -; fields `vertices`, `height,` `sidewall_angle`, and (optionally) `axis` -; will be initialized by the user; all remaining fields are -; derived properties that are computed internally. (So, morally -; they should be thought of as having been declared using -; `define-derived-property` or `define-post-processed-property,` -; except here the code that does the derivation or -; post-processing is implemented in C, not scheme.) +; fields `vertices_bottom`, `height,` (optionally) `axis`, +; and `sidewall_angle` will be initialized by the user; all +; remaining fields are derived properties that are computed +; internally. (So, morally, they should be thought of as having +; been declared using `define-derived-property` or +; `define-post-processed-property,` except here the code that does +; the derivation or post-processing is implemented in C, not scheme.) ; (b) The suffix _p (for "prism") is used to identify variables ; that store coordinates of points or components of vectors ; in the prism coordinate system. (The prism coordinate system From 093ec84446ae46e1e841ce5971cbdc82a1c2e020 Mon Sep 17 00:00:00 2001 From: danielwboyce Date: Tue, 14 Jan 2020 14:19:04 -0700 Subject: [PATCH 20/63] Fixes for correct compilation. --- utils/test-prism.c | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/utils/test-prism.c b/utils/test-prism.c index b99cea3..90be64a 100644 --- a/utils/test-prism.c +++ b/utils/test-prism.c @@ -129,11 +129,11 @@ vector3 random_point_in_box(vector3 min_corner, vector3 max_corner) { /* random point uniformly distributed over a planar polygon */ /* (all z coordinates are 0) */ /************************************************************************/ -vector3 random_point_in_polygon(prsm *prsm) { +vector3 random_point_in_polygon(prism *prsm) { // randomly choose a vertex and generate random point within the triangle // formed by that vertex, the next vertex, and the centroid vector3 *vertices_bottom = prsm->vertices_bottom.items; - int num_vertices = prsm->vertices_bottom_num_items; + int num_vertices = prsm->vertices_bottom.num_items; int which_vertex = rand() % num_vertices; vector3 v0 = {0, 0, 0}; vector3 v1 = vertices_bottom[which_vertex]; @@ -664,7 +664,7 @@ int main(int argc, char *argv[]) { fprintf(stderr, "bad vertex on line %i of %s", num_vertices, vertexfile); exit(1); } - vertices_bottom = (vector3 *)realloc(vertices, num_vertices * sizeof(vector3)); + vertices_bottom = (vector3 *)realloc(vertices_bottom, num_vertices * sizeof(vector3)); vertices_bottom[num_vertices - 1] = v; } fclose(f); From ca179579f4726c6d746ba52fcd81821813f6514a Mon Sep 17 00:00:00 2001 From: danielwboyce Date: Tue, 14 Jan 2020 16:30:39 -0700 Subject: [PATCH 21/63] * Calculations for vertices_top and vertices_top_p. * Update to normal to prism for compatibility with top polygon framework. --- utils/geom.c | 55 +++++++++++++++++++++++++++++----------------------- 1 file changed, 31 insertions(+), 24 deletions(-) diff --git a/utils/geom.c b/utils/geom.c index eaaedc9..f12fcd7 100644 --- a/utils/geom.c +++ b/utils/geom.c @@ -2330,6 +2330,7 @@ vector3 normal_to_prism(prism *prsm, vector3 pc) { double height = prsm->height; vector3 *vps_bottom = prsm->vertices_bottom_p.items; + vector3 *vps_diff_to_top = prsm->top_polygon_diff_vectors_p.items; int num_vertices = prsm->vertices_bottom_p.num_items; vector3 zhatp = {0.0, 0.0, 1.0}; @@ -2344,10 +2345,8 @@ vector3 normal_to_prism(prism *prsm, vector3 pc) { int nvp1 = (nv == (num_vertices - 1) ? 0 : nv + 1); vector3 v0p = vps_bottom[nv]; vector3 v1p = vector3_minus(vps_bottom[nvp1], vps_bottom[nv]); - // v2p needs to be changed to be from v0p to the corresponding vertex in the top polygon - vector3 v2p = axisp; + vector3 v2p = vps_diff_to_top[nv]; vector3 v3p = unit_vector3(vector3_cross(v1p, v2p)); - // quadrilateral determined {v0p, v0p+v1p, v0p+v2p, v0p+v1p+v2p} with normal vector v3p double s = min_distance_to_quadrilateral(pp, v0p, v1p, v2p, v3p); if (fabs(s) < min_distance) { min_distance = fabs(s); @@ -2557,34 +2556,36 @@ void init_prism(geometric_object *o) { } number theta = (K_PI/2) - prsm->sidewall_angle; - prsm->top_polygon_diff_vectors_p.num_items = num_vertices; - prsm->top_polygon_diff_vectors_p.items = (vector3 *)malloc(num_vertices * sizeof(vector3)); + prsm->vertices_top_p.num_items = num_vertices; + prsm->vertices_top_p.items = (vector3 *)malloc(num_vertices * sizeof(vector3)); for (nv = 0; nv < num_vertices; nv++) { number cx; - if (prsm->sidewall_angle == 0 ) { - cx = 1; - } - else if (prsm->vertices_bottom_p.items[nv].x == 0) { - cx = 0; - } - else { - cx = 1 - prsm->height / (abs(prsm->vertices_bottom_p.items[nv].x) * tan(theta)); + if (prsm->sidewall_angle == 0) { + cx = 1; + } else if (prsm->vertices_bottom_p.items[nv].x == 0) { + cx = 0; + } else { + cx = 1 - prsm->height / (abs(prsm->vertices_bottom_p.items[nv].x) * tan(theta)); } number cy; - if (prsm->sidewall_angle == 0 ) { - cy = 1; - } - else if (prsm->vertices_bottom_p.items[nv].y == 0) { - cy = 0; - } - else { - cy = 1 - prsm->height / (abs(prsm->vertices_bottom_p.items[nv].y) * tan(theta)); + if (prsm->sidewall_angle == 0) { + cy = 1; + } else if (prsm->vertices_bottom_p.items[nv].y == 0) { + cy = 0; + } else { + cy = 1 - prsm->height / (abs(prsm->vertices_bottom_p.items[nv].y) * tan(theta)); } - prsm->top_polygon_diff_vectors_p.items[nv].x = (cx - 1) * prsm->vertices_bottom_p.items[nv].x; - prsm->top_polygon_diff_vectors_p.items[nv].y = (cy - 1) * prsm->vertices_bottom_p.items[nv].y; - prsm->top_polygon_diff_vectors_p.items[nv].z = prsm->height; + prsm->vertices_top_p.items[nv].x = cx * prsm->vertices_bottom_p.items[nv].x; + prsm->vertices_top_p.items[nv].y = cy * prsm->vertices_bottom_p.items[nv].y; + prsm->vertices_top_p.items[nv].z = prsm->height; + } + + prsm->top_polygon_diff_vectors_p.num_items = num_vertices; + prsm->top_polygon_diff_vectors_p.items = (vector3 *)malloc(num_vertices * sizeof(vector3)); + for (nv = 0; nv < num_vertices; nv++) { + prsm->top_polygon_diff_vectors_p.items[nv] = vector3_minus(prsm->vertices_top_p.items[nv], prsm->vertices_bottom_p.items[nv]); } prsm->top_polygon_diff_vectors_scaled_p.num_items = num_vertices; @@ -2593,6 +2594,12 @@ void init_prism(geometric_object *o) { prsm->top_polygon_diff_vectors_scaled_p.items[nv] = vector3_scale(1/prsm->height, prsm->top_polygon_diff_vectors_p.items[nv]); } + prsm->vertices_top.num_items = num_vertices; + prsm->vertices_top.items = (vector3 *)malloc(num_vertices * sizeof(vector3)); + for (nv = 0; nv < num_vertices; nv++) { + prsm->vertices_top.items[nv] = prism_coordinate_p2c(prsm, prsm->vertices_top_p.items[nv]); + } + prsm->top_polygon_diff_vectors.num_items = num_vertices; prsm->top_polygon_diff_vectors.items = (vector3 *)malloc(num_vertices * sizeof(vector3)); for (nv = 0; nv < num_vertices; nv++) { From 24124dccb3a03138dde92fc57f8be6848fc5894e Mon Sep 17 00:00:00 2001 From: danielwboyce Date: Tue, 14 Jan 2020 16:45:06 -0700 Subject: [PATCH 22/63] Update to get_prism_bounding_box for compatibility with top polygon framework. --- utils/geom.c | 6 ++++-- 1 file changed, 4 insertions(+), 2 deletions(-) diff --git a/utils/geom.c b/utils/geom.c index f12fcd7..817e24b 100644 --- a/utils/geom.c +++ b/utils/geom.c @@ -2370,14 +2370,16 @@ vector3 normal_to_prism(prism *prsm, vector3 pc) { /***************************************************************/ void get_prism_bounding_box(prism *prsm, geom_box *box) { vector3 *vertices_bottom = prsm->vertices_bottom.items; + vector3 *vertices_top = prsm->vertices_top.items; int num_vertices = prsm->vertices_bottom.num_items; box->low = box->high = vertices_bottom[0]; int nv, fc; for (nv = 0; nv < num_vertices; nv++) for (fc = 0; fc < 2; fc++) // 'floor,ceiling' { - vector3 v = vertices_bottom[nv]; - if (fc == 1) v = vector3_plus(v, vector3_scale(prsm->height, prsm->axis)); + vector3 v; + if (fc == 0) v = vertices_bottom[nv]; + if (fc == 1) v = vertices_top[nv]; box->low.x = fmin(box->low.x, v.x); box->low.y = fmin(box->low.y, v.y); From 72462b43598b693af8741d52ff3a1c5ccbe3f7be Mon Sep 17 00:00:00 2001 From: danielwboyce Date: Tue, 14 Jan 2020 17:43:01 -0700 Subject: [PATCH 23/63] Update to intersect_line_with_prism for compatibility with top polygon framework. --- utils/geom.c | 15 ++++++++++++--- 1 file changed, 12 insertions(+), 3 deletions(-) diff --git a/utils/geom.c b/utils/geom.c index 817e24b..909e4c3 100644 --- a/utils/geom.c +++ b/utils/geom.c @@ -2157,13 +2157,21 @@ static int dcmp(const void *pd1, const void *pd2) { int intersect_line_with_prism(prism *prsm, vector3 pc, vector3 dc, double *slist) { vector3 pp = prism_coordinate_c2p(prsm, pc); vector3 dp = prism_vector_c2p(prsm, dc); - vector3 *vps = prsm->vertices_bottom_p.items; + vector3 *vps_bottom = prsm->vertices_bottom_p.items; + vector3 *vps_diff_scaled = prsm->top_polygon_diff_vectors_scaled_p.items; + vector3 *vps_top = prsm->vertices_top_p.items; int num_vertices = prsm->vertices_bottom_p.num_items; double height = prsm->height; + vector3 nodes_at_z[num_vertices]; + int nv; + for (nv = 0; nv < num_vertices; nv++) { + nodes_at_z[nv] = vector3_plus(vps_bottom[nv], vector3_scale(pp.z, vps_diff_scaled[nv])); + } + // use length of first polygon edge as a length scale for judging // lengths to be small or large - double length_scale = vector3_norm(vector3_minus(vps[1], vps[0])); + double length_scale = vector3_norm(vector3_minus(nodes_at_z[1], nodes_at_z[0])); // identify intersections with prism side faces int num_intersections = 0; @@ -2176,7 +2184,7 @@ int intersect_line_with_prism(prism *prsm, vector3 pc, vector3 dc, double *slist // intersection of the XY-plane projection of the line with the // polygon edge between vertices (nv,nv+1). double s; - int status = intersect_line_with_segment(pp, vps[nv], vps[nvp1], dp, &s); + int status = intersect_line_with_segment(pp, nodes_at_z[nv], nodes_at_z[nvp1], dp, &s); if (status == NON_INTERSECTING || status == ON_RAY) continue; // OK, we know the XY-plane projection of the line intersects the polygon edge; @@ -2198,6 +2206,7 @@ int intersect_line_with_prism(prism *prsm, vector3 pc, vector3 dc, double *slist for (LowerUpper = 0; LowerUpper < 2; LowerUpper++) { double z0p = LowerUpper ? height : 0.0; double s = (z0p - pp.z) / dp.z; + vector3 *vps = LowerUpper ? vps_top : vps_bottom; if (!node_in_polygon(pp.x + s * dp.x, pp.y + s * dp.y, vps, num_vertices)) continue; slist[num_intersections++] = s; } From d37689fbdc80db1e249f9189e4df9281840ee9ca Mon Sep 17 00:00:00 2001 From: danielwboyce Date: Tue, 14 Jan 2020 18:08:48 -0700 Subject: [PATCH 24/63] Update to geom_object_volume for compatibility with top polygon framework. To do so, I took the RMS area of the bottom polygon area and top polygon area then multiplied by the height of the prism. --- utils/geom.c | 11 ++++++++--- 1 file changed, 8 insertions(+), 3 deletions(-) diff --git a/utils/geom.c b/utils/geom.c index 909e4c3..caffb41 100644 --- a/utils/geom.c +++ b/utils/geom.c @@ -915,14 +915,19 @@ double geom_object_volume(GEOMETRIC_OBJECT o) { case GEOM PRISM: { // needs updating for non-normal sidewalls vector3_list vertices_bottom = o.subclass.prism_data->vertices_bottom_p; - double area = 0; + vector3_list vertices_top = o.subclass.prism_data->vertices_top_p; + double area_bottom = 0; + double area_top = 0; int i; for (i = 0; i < vertices_bottom.num_items; ++i) { int i1 = (i + 1) % vertices_bottom.num_items; - area += 0.5 * (vertices_bottom.items[i1].x - vertices_bottom.items[i].x) * + area_bottom += 0.5 * (vertices_bottom.items[i1].x - vertices_bottom.items[i].x) * (vertices_bottom.items[i1].y + vertices_bottom.items[i].y); + area_top += 0.5 * (vertices_top.items[i1].x - vertices_top.items[i].x) * + (vertices_top.items[i1].y + vertices_top.items[i].y); } - return fabs(area) * o.subclass.prism_data->height; + double area_rms = sqrt((pow(fabs(area_bottom), 2) + pow(fabs(area_top), 2))/2); + return area_rms * o.subclass.prism_data->height; } default: return 0; /* unsupported object types? */ } From d2e2868f1f94f90f73272a7b52de031f43e6a075 Mon Sep 17 00:00:00 2001 From: danielwboyce Date: Wed, 15 Jan 2020 11:53:17 -0700 Subject: [PATCH 25/63] oops --- utils/geom.c | 1 - 1 file changed, 1 deletion(-) diff --git a/utils/geom.c b/utils/geom.c index caffb41..0502d96 100644 --- a/utils/geom.c +++ b/utils/geom.c @@ -2180,7 +2180,6 @@ int intersect_line_with_prism(prism *prsm, vector3 pc, vector3 dc, double *slist // identify intersections with prism side faces int num_intersections = 0; - int nv; for (nv = 0; nv < num_vertices; nv++) { int nvp1 = nv + 1; if (nvp1 == num_vertices) nvp1 = 0; From 0dc29b06115ed03f0b7c9902b590455b83dfa721 Mon Sep 17 00:00:00 2001 From: danielwboyce Date: Wed, 15 Jan 2020 12:12:24 -0700 Subject: [PATCH 26/63] Update to min_distance_to_prism_roof_or_ceiling for compatibility in with top polygon --- utils/geom.c | 11 ++++++++--- 1 file changed, 8 insertions(+), 3 deletions(-) diff --git a/utils/geom.c b/utils/geom.c index 0502d96..55ed1e7 100644 --- a/utils/geom.c +++ b/utils/geom.c @@ -2316,10 +2316,15 @@ double min_distance_to_quadrilateral(vector3 p, vector3 o, vector3 v1, vector3 v // fc==0/1 for floor/ceiling double min_distance_to_prism_roof_or_ceiling(vector3 pp, prism *prsm, int fc) { - vector3 *vps = prsm->vertices_bottom_p.items; int num_vertices = prsm->vertices_bottom_p.num_items; - vector3 op = {0.0, 0.0, 0.0}; - if (fc == 1) op.z = prsm->height; // origin of floor/ceiling + vector3 op = {0.0, 0.0, 0.0}; // origin of floor/ceiling + if (fc == 1) { + vector3 *vps = prsm->vertices_top_p.items; + op.z = prsm->height; + } + else { + vector3 *vps = prsm->vertices_bottom_p.items; + } vector3 zhatp = {0, 0, 1.0}; double s = normal_distance_to_plane(pp, op, vps[0], vps[1], zhatp, 0); vector3 ppProj = From 8d5eb91c620e5494afa9cd261327b0264dbf8dbb Mon Sep 17 00:00:00 2001 From: danielwboyce Date: Tue, 21 Jan 2020 11:02:13 -0700 Subject: [PATCH 27/63] Rough draft of algorithm where offset of the top polygon's edges is found and then vertices are calculated from the intersection of those edges. --- utils/geom.c | 127 ++++++++++++++++++++++++++++++++++++++++----------- 1 file changed, 100 insertions(+), 27 deletions(-) diff --git a/utils/geom.c b/utils/geom.c index 55ed1e7..cb542c1 100644 --- a/utils/geom.c +++ b/utils/geom.c @@ -2318,12 +2318,13 @@ double min_distance_to_quadrilateral(vector3 p, vector3 o, vector3 v1, vector3 v double min_distance_to_prism_roof_or_ceiling(vector3 pp, prism *prsm, int fc) { int num_vertices = prsm->vertices_bottom_p.num_items; vector3 op = {0.0, 0.0, 0.0}; // origin of floor/ceiling + vector3 *vps; if (fc == 1) { - vector3 *vps = prsm->vertices_top_p.items; + vps = prsm->vertices_top_p.items; op.z = prsm->height; } else { - vector3 *vps = prsm->vertices_bottom_p.items; + vps = prsm->vertices_bottom_p.items; } vector3 zhatp = {0, 0, 1.0}; double s = normal_distance_to_plane(pp, op, vps[0], vps[1], zhatp, 0); @@ -2559,75 +2560,147 @@ void init_prism(geometric_object *o) { for (nv = 0; nv < num_vertices; nv++) prsm->vertices_bottom_p.items[nv] = prism_coordinate_c2p(prsm, vertices_bottom[nv]); - // calculate difference vectors between bottom polygon and the top polygon, where + // calculate difference vertices of the top polygon and vectors between bottom + // polygon and the top polygon, where // * the bottom polygon is the one passed in to the the make_prism() function, // stored in vertices_bottom and vertices_bottom_p // * the top polygon is the top surface (parallel to the bottom polygon) resulting // from the extrusion of the bottom polygon. Whether or not the extrusion tapers // is dependent on the value of sidewall_angle. - // ** The value of each of the top polygon vertices can be found - // vertices_bottom_p + top_polygon_diff_vectors_p - // vertices_bottom + top_polygon_diff_vectors - // ** A linearly interpolated value of the polygon vertices between the bottom + // The top polygon is calculated by first copying the values of vertices_bottom_p into + // vertices_top_p, except z=prsm->height for all top vertices. If prsm->sidewall_angle==0 + // then no further calculations are performed on the top vertices. If not, we know that + // all EDGES of the the top polygon will be offset so that in the xy plane they are + // parallel to the edges of the bottom polygon. The offset amount is determined by the + // sidewall angle and the height of the prism. To perform the calculation, each of the + // edges of the top polygon (without an offset) are stored in an array of edges (edge is + // a struct defined if prsm->sidewall_angle!=0 containing the endpoints a1 a2, with a + // third vector v defined a2-a1). Then the vector normal to v is calculated, and the + // offset vector. It is determined whether the edge will be offset in the positive or + // negative direction based on the direction where points are in the polygon and whether + // prsm->sidewall_angle is positive or negative. After the offsets are applied to the + // edges, the intersections between the new edges are calculated, which are the new + // values of vertices_top_p. + // + // Some side notes on the difference vectors: + // * The value of each of the top polygon vertices can be found + // vertices_bottom_p + top_polygon_diff_vectors_p + // vertices_bottom + top_polygon_diff_vectors + // * A linearly interpolated value of the polygon vertices between the bottom // polygon and the top can be found - // vertices_bottom_p + top_polygon_diff_vectors_scaled_p * z + // vertices_bottom_p + top_polygon_diff_vectors_scaled_p * z if (isnan(prsm->sidewall_angle)) { prsm->sidewall_angle = 0.0; } - number theta = (K_PI/2) - prsm->sidewall_angle; + number theta = (K_PI/2) - abs(prsm->sidewall_angle); prsm->vertices_top_p.num_items = num_vertices; prsm->vertices_top_p.items = (vector3 *)malloc(num_vertices * sizeof(vector3)); + CHECK(prsm->vertices_top_p.items, "out of memory"); + memcpy(prsm->vertices_top_p.items, prsm->vertices_bottom_p.items, num_vertices * sizeof(vector3)); for (nv = 0; nv < num_vertices; nv++) { - number cx; - if (prsm->sidewall_angle == 0) { - cx = 1; - } else if (prsm->vertices_bottom_p.items[nv].x == 0) { - cx = 0; - } else { - cx = 1 - prsm->height / (abs(prsm->vertices_bottom_p.items[nv].x) * tan(theta)); - } + prsm->vertices_top_p.items[nv].z = prsm->height; + } + + if (prsm->sidewall_angle != 0.0) { + struct edge { + vector3 a1, a2, v; // v will be defined as a2 - a1 + } edge; + + edge *top_polygon_edges; + top_polygon_edges = (edge *)malloc(num_vertices * sizeof(edge)); + number w = prsm->height / tan(theta); - number cy; - if (prsm->sidewall_angle == 0) { - cy = 1; - } else if (prsm->vertices_bottom_p.items[nv].y == 0) { - cy = 0; - } else { - cy = 1 - prsm->height / (abs(prsm->vertices_bottom_p.items[nv].y) * tan(theta)); + for (nv = 0; nv < num_vertices; nv++) { + top_polygon_edges[nv].a1 = prsm->vertices_top_p.items[(nv - 1 == -1 ? num_vertices - 1 : nv - 1)]; + top_polygon_edges[nv].a2 = prsm->vertices_top_p.items[nv]; + top_polygon_edges[nv].v = vector3_minus(top_polygon_edges[nv].a2, top_polygon_edges[nv].a1); + + vector3 normal_vector; + normal_vector.x = top_polygon_edges[nv].v.y; + normal_vector.y = -1 * top_polygon_edges[nv].v.x; + normal_vector.z = 0; + normal_vector = unit_vector3(normal_vector); + vector3 offset = vector3_scale(w, normal_vector); + + vector3 midpoint = vector3_plus(top_polygon_edges[nv].a1, vector3_scale(0.5, top_polygon_edges[nv].v)); + boolean midpoint_on_side_of_postive_offset_is_in_polygon = node_in_or_on_polygon(vector3_plus(midpoint, vector3_scale(1e-3, offset)), prsm->vertices_top_p.items, prsm->vertices_top_p.num_items, 1); + + if (midpoint_on_side_of_postive_offset_is_in_polygon) { + // positive sidewall angles means the prism tapers in towards to the rest of the prism body + if (prsm->sidewall_angle > 0) { + top_polygon_edges[nv].a1 = vector3_plus(top_polygon_edges[nv].a1, offset); + top_polygon_edges[nv].a2 = vector3_plus(top_polygon_edges[nv].a2, offset); + } + // negative sidewall angles means the prism tapers out away from the rest of the prism body + else { + top_polygon_edges[nv].a1 = vector3_minus(top_polygon_edges[nv].a1, offset); + top_polygon_edges[nv].a2 = vector3_minus(top_polygon_edges[nv].a2, offset); + } + } + else { + // positive sidewall angles means the prism tapers in towards to the rest of the prism body + if (prsm->sidewall_angle > 0) { + top_polygon_edges[nv].a1 = vector3_minus(top_polygon_edges[nv].a1, offset); + top_polygon_edges[nv].a2 = vector3_minus(top_polygon_edges[nv].a2, offset); + } + // negative sidewall angles means the prism tapers out away from the rest of the prism body + else { + top_polygon_edges[nv].a1 = vector3_plus(top_polygon_edges[nv].a1, offset); + top_polygon_edges[nv].a2 = vector3_plus(top_polygon_edges[nv].a2, offset); + } + } } - prsm->vertices_top_p.items[nv].x = cx * prsm->vertices_bottom_p.items[nv].x; - prsm->vertices_top_p.items[nv].y = cy * prsm->vertices_bottom_p.items[nv].y; - prsm->vertices_top_p.items[nv].z = prsm->height; + for (nv = 0; nv < num_vertices; nv++) { + number x1 = top_polygon_edges[nv].a1.x; + number y1 = top_polygon_edges[nv].a1.y; + number x2 = top_polygon_edges[nv].a2.x; + number y2 = top_polygon_edges[nv].a2.y; + number x3 = top_polygon_edges[(nv + 1 == num_vertices ? 0 : nv + 1)].a1.x; + number y3 = top_polygon_edges[(nv + 1 == num_vertices ? 0 : nv + 1)].a1.y; + number x4 = top_polygon_edges[(nv + 1 == num_vertices ? 0 : nv + 1)].a2.x; + number y4 = top_polygon_edges[(nv + 1 == num_vertices ? 0 : nv + 1)].a2.y; + + // Intersection point calculated with https://en.wikipedia.org/wiki/Line%E2%80%93line_intersection#Given_two_points_on_each_line + number px = ((x1*y2-y1*x2)*(x3-x4)-(x1-x2)*(x3*y4-y3*x4)) / ((x1-x2)*(y3-y4)-(y1-y2)*(x3-x4)); + number py = ((x1*y2-y1*x2)*(y3-y4)-(y1-y2)*(x3*y4-y3*x4)) / ((x1-x2)*(y3-y4)-(y1-y2)*(x3-x4)); + prsm->vertices_top_p.items[nv].x = px; + prsm->vertices_top_p.items[nv].y = py; + } } prsm->top_polygon_diff_vectors_p.num_items = num_vertices; prsm->top_polygon_diff_vectors_p.items = (vector3 *)malloc(num_vertices * sizeof(vector3)); + CHECK(prsm->top_polygon_diff_vectors_p.items, "out of memory"); for (nv = 0; nv < num_vertices; nv++) { prsm->top_polygon_diff_vectors_p.items[nv] = vector3_minus(prsm->vertices_top_p.items[nv], prsm->vertices_bottom_p.items[nv]); } prsm->top_polygon_diff_vectors_scaled_p.num_items = num_vertices; prsm->top_polygon_diff_vectors_scaled_p.items = (vector3 *)malloc(num_vertices * sizeof(vector3)); + CHECK(prsm->top_polygon_diff_vectors_scaled_p.items, "out of memory"); for (nv = 0; nv < num_vertices; nv++) { prsm->top_polygon_diff_vectors_scaled_p.items[nv] = vector3_scale(1/prsm->height, prsm->top_polygon_diff_vectors_p.items[nv]); } prsm->vertices_top.num_items = num_vertices; prsm->vertices_top.items = (vector3 *)malloc(num_vertices * sizeof(vector3)); + CHECK(prsm->vertices_top.items, "out of memory"); for (nv = 0; nv < num_vertices; nv++) { prsm->vertices_top.items[nv] = prism_coordinate_p2c(prsm, prsm->vertices_top_p.items[nv]); } prsm->top_polygon_diff_vectors.num_items = num_vertices; prsm->top_polygon_diff_vectors.items = (vector3 *)malloc(num_vertices * sizeof(vector3)); + CHECK(prsm->top_polygon_diff_vectors.items, "out of memory"); for (nv = 0; nv < num_vertices; nv++) { prsm->top_polygon_diff_vectors.items[nv] = prism_vector_p2c(prsm, prsm->top_polygon_diff_vectors_p.items[nv]); } prsm->top_polygon_diff_vectors_scaled.num_items = num_vertices; prsm->top_polygon_diff_vectors_scaled.items = (vector3 *)malloc(num_vertices * sizeof(vector3)); + CHECK(prsm->top_polygon_diff_vectors_scaled.items, "out of memory"); for (nv = 0; nv < num_vertices; nv++) { prsm->top_polygon_diff_vectors_scaled.items[nv] = prism_vector_p2c(prsm, prsm->top_polygon_diff_vectors_scaled_p.items[nv]); } From f43f12866438efa25b6873704bd6bb15f58cfa74 Mon Sep 17 00:00:00 2001 From: danielwboyce Date: Tue, 21 Jan 2020 11:18:01 -0700 Subject: [PATCH 28/63] Updates to the comments --- utils/geom.c | 39 +++++++++++++++++++++++---------------- 1 file changed, 23 insertions(+), 16 deletions(-) diff --git a/utils/geom.c b/utils/geom.c index cb542c1..218f373 100644 --- a/utils/geom.c +++ b/utils/geom.c @@ -2560,27 +2560,34 @@ void init_prism(geometric_object *o) { for (nv = 0; nv < num_vertices; nv++) prsm->vertices_bottom_p.items[nv] = prism_coordinate_c2p(prsm, vertices_bottom[nv]); - // calculate difference vertices of the top polygon and vectors between bottom - // polygon and the top polygon, where + // Calculate difference vertices of the top polygon and vectors between bottom + // polygon and the top polygon, where: // * the bottom polygon is the one passed in to the the make_prism() function, - // stored in vertices_bottom and vertices_bottom_p + // stored in vertices_bottom and vertices_bottom_p, // * the top polygon is the top surface (parallel to the bottom polygon) resulting // from the extrusion of the bottom polygon. Whether or not the extrusion tapers // is dependent on the value of sidewall_angle. + // // The top polygon is calculated by first copying the values of vertices_bottom_p into - // vertices_top_p, except z=prsm->height for all top vertices. If prsm->sidewall_angle==0 - // then no further calculations are performed on the top vertices. If not, we know that - // all EDGES of the the top polygon will be offset so that in the xy plane they are - // parallel to the edges of the bottom polygon. The offset amount is determined by the - // sidewall angle and the height of the prism. To perform the calculation, each of the - // edges of the top polygon (without an offset) are stored in an array of edges (edge is - // a struct defined if prsm->sidewall_angle!=0 containing the endpoints a1 a2, with a - // third vector v defined a2-a1). Then the vector normal to v is calculated, and the - // offset vector. It is determined whether the edge will be offset in the positive or - // negative direction based on the direction where points are in the polygon and whether - // prsm->sidewall_angle is positive or negative. After the offsets are applied to the - // edges, the intersections between the new edges are calculated, which are the new - // values of vertices_top_p. + // vertices_top_p, except z=prsm->height for all top vertices. If prsm->sidewall_angle + // is equal to zero, then no further calculations are performed on the top vertices. + // If not, we know that all EDGES of the the top polygon will be offset so that in the + // xy plane they are parallel to the edges of the bottom polygon. The offset amount is + // determined by the sidewall angle and the height of the prism. To perform the + // calculation, each of the edges of the top polygon (without an offset) are stored in + // an array of edges (edge is a struct defined if prsm->sidewall_angle!=0 containing + // the endpoints a1 a2, with a third vector v defined a2-a1). Then the vector normal to + // v is calculated, and the offset vector. A test is performed to determine in which + // direction (the direction of +offset or -offset) from the edge we can find points + // inside the polygon by performing a node_in_or_on_polygon test at a finite distance + // away from the midpoint of the edge: + // edge.a1 + 0.5*edge.v + 1e-3*offset. + // This information is used to determine in which direction the offset of the edge is + // applied, in conjunction with whether prsm->sidewall_angle is positive or negative + // (if positive, the offset will be applied in towards the points where + // node_in_or_on_polygon is true, else the offset will be applied out away from those + // points). After the offsets are applied to the edges, the intersections between the + // new edges are calculated, which are the new values of vertices_top_p. // // Some side notes on the difference vectors: // * The value of each of the top polygon vertices can be found From 4e830ed65dfdfb8ef7616b28b67d2b472decc650 Mon Sep 17 00:00:00 2001 From: danielwboyce Date: Tue, 21 Jan 2020 13:20:48 -0700 Subject: [PATCH 29/63] Fixed typo (was using abs instead of fabs) --- utils/geom.c | 5 ++--- 1 file changed, 2 insertions(+), 3 deletions(-) diff --git a/utils/geom.c b/utils/geom.c index 218f373..1656156 100644 --- a/utils/geom.c +++ b/utils/geom.c @@ -2599,8 +2599,7 @@ void init_prism(geometric_object *o) { if (isnan(prsm->sidewall_angle)) { prsm->sidewall_angle = 0.0; } - number theta = (K_PI/2) - abs(prsm->sidewall_angle); - + number theta = (K_PI/2) - fabs(prsm->sidewall_angle); prsm->vertices_top_p.num_items = num_vertices; prsm->vertices_top_p.items = (vector3 *)malloc(num_vertices * sizeof(vector3)); CHECK(prsm->vertices_top_p.items, "out of memory"); @@ -2610,7 +2609,7 @@ void init_prism(geometric_object *o) { } if (prsm->sidewall_angle != 0.0) { - struct edge { + typedef struct { vector3 a1, a2, v; // v will be defined as a2 - a1 } edge; From 0daf5b6c322664179014c08bfb5102efcf4faabe Mon Sep 17 00:00:00 2001 From: danielwboyce Date: Tue, 21 Jan 2020 15:01:59 -0700 Subject: [PATCH 30/63] Update to run unit test 5 in test-prism.c with concave octagonal c shape --- utils/test-prism.c | 61 ++++++++++++++++++++++++++++++++++------------ 1 file changed, 46 insertions(+), 15 deletions(-) diff --git a/utils/test-prism.c b/utils/test-prism.c index 90be64a..05cd517 100644 --- a/utils/test-prism.c +++ b/utils/test-prism.c @@ -468,26 +468,57 @@ int test_point_in_polygon(int write_log) { int test_sidewall_prisms_to_gnuplot() { void *m = NULL; - int num_nodes = 4; - vector3 nodes[num_nodes]; - nodes[0] = make_vector3(-1.0, -1.0, 0.0); - nodes[1] = make_vector3(-1.0, 1.0, 0.0); - nodes[2] = make_vector3(1.0, 1.0, 0.0); - nodes[3] = make_vector3(1.0, -1.0, 0.0); - - double height = 10; + int num_nodes_square = 4; + vector3 nodes_square[num_nodes_square]; + nodes_square[0] = make_vector3(-1.0, -1.0, 0.0); + nodes_square[1] = make_vector3(-1.0, 1.0, 0.0); + nodes_square[2] = make_vector3(1.0, 1.0, 0.0); + nodes_square[3] = make_vector3(1.0, -1.0, 0.0); + + double height_square = 10; vector3 zhat = make_vector3(0, 0, 1); double normal_sidewall = 0; - geometric_object normal_sidewall_geom_object = make_prism(m, nodes, num_nodes, height, zhat, normal_sidewall); - prism *normal_sidewall_prism = normal_sidewall_geom_object.subclass.prism_data; + geometric_object square_normal_sidewall_geom_object = make_prism(m, nodes_square, num_nodes_square, height_square, zhat, normal_sidewall); + prism *square_normal_sidewall_prism = square_normal_sidewall_geom_object.subclass.prism_data; double one_degree_sidewall = 1.0 * 2 * K_PI / 360.0; - geometric_object one_degree_sidewall_geom_object = make_prism(m, nodes, num_nodes, height, zhat, one_degree_sidewall); - prism *one_degree_sidewall_prism = one_degree_sidewall_geom_object.subclass.prism_data; - - prism2gnuplot(normal_sidewall_prism, "normal_sidewall_gnu_plot.dat"); - prism2gnuplot(one_degree_sidewall_prism, "one_degree_sidewall_gnu_plot.dat"); + geometric_object square_one_degree_sidewall_geom_object = make_prism(m, nodes_square, num_nodes_square, height_square, zhat, one_degree_sidewall); + prism *square_one_degree_sidewall_prism = square_one_degree_sidewall_geom_object.subclass.prism_data; + + prism2gnuplot(square_normal_sidewall_prism, "square_normal_sidewall_gnu_plot.dat"); + prism2gnuplot(square_one_degree_sidewall_prism, "square_one_degree_sidewall_gnu_plot.dat"); + + int num_nodes_octagon_c = 16; + vector3 nodes_octagon_c[num_nodes_octagon_c]; + nodes_octagon_c[0] = make_vector3(114.905, 88.7434, 0.0); + nodes_octagon_c[1] = make_vector3(88.7434, 114.905, 0.0); + nodes_octagon_c[2] = make_vector3(51.7447, 114.905, 0.0); + nodes_octagon_c[3] = make_vector3(25.5827, 88.7434, 0.0); + nodes_octagon_c[4] = make_vector3(25.5827, 51.7447, 0.0); + nodes_octagon_c[5] = make_vector3(51.7447, 25.5827, 0.0); + nodes_octagon_c[6] = make_vector3(88.7434, 25.5827, 0.0); + nodes_octagon_c[7] = make_vector3(114.905, 51.7447, 0.0); + nodes_octagon_c[8] = make_vector3(140.488, 41.1477, 0.0); + nodes_octagon_c[9] = make_vector3(99.3401, 0.0, 0.0); + nodes_octagon_c[10] = make_vector3(41.1477, 0.0, 0.0); + nodes_octagon_c[11] = make_vector3(0.0, 41.1477, 0.0); + nodes_octagon_c[12] = make_vector3(0.0, 99.3401, 0.0); + nodes_octagon_c[13] = make_vector3(41.1477, 140.488, 0.0); + nodes_octagon_c[14] = make_vector3(99.3401, 140.488, 0.0); + nodes_octagon_c[15] = make_vector3(140.488, 99.3401, 0.0); + + double height_octagon_c = 127; + + geometric_object octagon_c_normal_sidewall_geom_object = make_prism(m, nodes_octagon_c, num_nodes_octagon_c, height_octagon_c, zhat, normal_sidewall); + prism *octagon_c_normal_sidewall_prism = octagon_c_normal_sidewall_geom_object.subclass.prism_data; + + double two_half_degree_sidewall = 2.5 * 2 * K_PI / 360.0; + geometric_object octagon_c_two_half_degree_sidewall_geom_object = make_prism(m, nodes_octagon_c, num_nodes_octagon_c, height_octagon_c, zhat, two_half_degree_sidewall); + prism *octagon_c_two_half_degree_sidewall_prism = octagon_c_two_half_degree_sidewall_geom_object.subclass.prism_data; + + prism2gnuplot(octagon_c_normal_sidewall_prism, "octagon_c_normal_sidewall_gnu_plot.dat"); + prism2gnuplot(octagon_c_two_half_degree_sidewall_prism, "octagon_c_two_half_degree_sidewall_gnu_plot.dat"); return 0; } From 17f97a3ed1b306ad000a421e37e81ad91f9a4643 Mon Sep 17 00:00:00 2001 From: danielwboyce Date: Tue, 21 Jan 2020 20:27:51 -0700 Subject: [PATCH 31/63] Update to calculate prism volume with the triangular wedges trick. --- utils/geom.c | 121 ++++++++++++++++++++++++++++++++++++++++++++------- 1 file changed, 106 insertions(+), 15 deletions(-) diff --git a/utils/geom.c b/utils/geom.c index 1656156..94c0c29 100644 --- a/utils/geom.c +++ b/utils/geom.c @@ -77,6 +77,7 @@ static boolean point_in_prism(prism *prsm, vector3 pc); static vector3 normal_to_prism(prism *prsm, vector3 pc); static double intersect_line_segment_with_prism(prism *prsm, vector3 pc, vector3 dc, double a, double b); +static double get_prism_volume(prism *prsm); static void get_prism_bounding_box(prism *prsm, geom_box *box); static void display_prism_info(int indentby, geometric_object *o); static void init_prism(geometric_object *o); @@ -913,21 +914,7 @@ double geom_object_volume(GEOMETRIC_OBJECT o) { return o.subclass.block_data->which_subclass == BLK BLOCK_SELF ? vol : vol * (K_PI / 6); } case GEOM PRISM: { - // needs updating for non-normal sidewalls - vector3_list vertices_bottom = o.subclass.prism_data->vertices_bottom_p; - vector3_list vertices_top = o.subclass.prism_data->vertices_top_p; - double area_bottom = 0; - double area_top = 0; - int i; - for (i = 0; i < vertices_bottom.num_items; ++i) { - int i1 = (i + 1) % vertices_bottom.num_items; - area_bottom += 0.5 * (vertices_bottom.items[i1].x - vertices_bottom.items[i].x) * - (vertices_bottom.items[i1].y + vertices_bottom.items[i].y); - area_top += 0.5 * (vertices_top.items[i1].x - vertices_top.items[i].x) * - (vertices_top.items[i1].y + vertices_top.items[i].y); - } - double area_rms = sqrt((pow(fabs(area_bottom), 2) + pow(fabs(area_top), 2))/2); - return area_rms * o.subclass.prism_data->height; + return get_prism_volume(o.subclass.prism_data); } default: return 0; /* unsupported object types? */ } @@ -2384,6 +2371,110 @@ vector3 normal_to_prism(prism *prsm, vector3 pc) { return prism_vector_p2c(prsm, retval); } +/***************************************************************/ +/* Compute the area of a polygon using its vertices. */ +/***************************************************************/ +double get_area_of_polygon_from_nodes(vector3 *nodes, int num_nodes){ + double area = 0; + int i; + for (i = 0; i < num_nodes; ++i) { + int i1 = (i + 1) % num_nodes; + area += 0.5 * (nodes[i1].x - nodes[i].x) * + (nodes[i1].y + nodes[i].y); + } + return fabs(area); +} + +/***************************************************************/ +/* This computes the volume of an irregular triangular prism */ +/* following the scheme of http://darrenirvine.blogspot.com/2011/10/volume-of-irregular-triangular-prism.html */ +/* The two end triangles have points a, b, and c. Angle abc */ +/* is right, and angles bac and acb are acute, of course. The */ +/* primary constraint for this method is that the lines be- */ +/* tween 'a's between triangles, betweens 'b's between */ +/* triangles, and between 'c's between triangles must all be */ +/* parallel, though the end triangles need not be parallel. */ + +/***************************************************************/ +double get_volume_irregular_triangular_prism(vector3 a0, vector3 b0, vector3 c0, vector3 a1, vector3 b1, vector3 c1) { + vector3 side_a = vector3_minus(a1, a0); + vector3 side_b = vector3_minus(b1, b0); + vector3 side_c = vector3_minus(c1, c0); + if (vector3_norm(vector3_cross(side_a, side_b)) != 0 || + vector3_norm(vector3_cross(side_b, side_c)) != 0 || + vector3_norm(vector3_cross(side_c, side_a)) != 0) { + //throw an error + } + double length_side_a = vector3_norm(side_a); + double length_side_b = vector3_norm(side_b); + double length_side_c = vector3_norm(side_c); + double average_length = (length_side_a + length_side_b + length_side_c) / 3.0; + + vector3 point_on_plane = a0; + vector3 plane_normal_vector = unit_vector3(side_a); + vector3 plane_to_a1 = vector3_minus(a1, point_on_plane); + vector3 plane_to_b1 = vector3_minus(b1, point_on_plane); + vector3 plane_to_c1 = vector3_minus(c1, point_on_plane); + vector3 proj_plane_to_a1_on_normal_vector = vector3_scale(vector3_dot(plane_normal_vector, plane_to_a1), plane_normal_vector); + vector3 proj_plane_to_b1_on_normal_vector = vector3_scale(vector3_dot(plane_normal_vector, plane_to_b1), plane_normal_vector); + vector3 proj_plane_to_c1_on_normal_vector = vector3_scale(vector3_dot(plane_normal_vector, plane_to_c1), plane_normal_vector); + vector3 a1_on_plane = vector3_minus(a1, proj_plane_to_a1_on_normal_vector); + vector3 b1_on_plane = vector3_minus(b1, proj_plane_to_b1_on_normal_vector); + vector3 c1_on_plane = vector3_minus(c1, proj_plane_to_c1_on_normal_vector); + double base = vector3_norm(vector3_minus(c1_on_plane, b1_on_plane)); + double height = vector3_norm(vector3_minus(a1_on_plane, b1_on_plane)); + double cross_sectional_area = fabs(0.5 * base * height); + + return fabs(average_length * cross_sectional_area); +} + +/***************************************************************/ +/***************************************************************/ +/***************************************************************/ +double get_prism_volume(prism *prsm) { + if (prsm->sidewall_angle == 0.0) { + return get_area_of_polygon_from_nodes(prsm->vertices_bottom_p.items, prsm->vertices_bottom_p.num_items) * fabs(prsm->height); + } + else { + int num_vertices = prsm->vertices_bottom_p.num_items; + double bottom_polygon_area = get_area_of_polygon_from_nodes(prsm->vertices_bottom_p.items, prsm->vertices_bottom_p.num_items); + double top_polygon_area = get_area_of_polygon_from_nodes(prsm->vertices_top_p.items, prsm->vertices_top_p.num_items); + double volume; + vector3 *wedges_a; + wedges_a = (vector3 *)malloc(num_vertices * sizeof(vector3)); + CHECK(wedges_a, "out of memory"); + vector3 *wedges_b; + wedges_b = (vector3 *)malloc(num_vertices * sizeof(vector3)); + CHECK(wedges_b, "out of memory"); + vector3 *wedges_c; + wedges_b = (vector3 *)malloc(num_vertices * sizeof(vector3)); + CHECK(wedges_c, "out of memory"); + if (bottom_polygon_area > top_polygon_area) { + volume = fabs(top_polygon_area * prsm->height); + memcpy(wedges_a, prsm->vertices_top_p.items, num_vertices * sizeof(vector3)); + memcpy(wedges_b, prsm->vertices_top_p.items, num_vertices * sizeof(vector3)); + for (int nv = 0; nv < num_vertices; nv++) { + wedges_b[nv].z = 0.0; + } + memcpy(wedges_c, prsm->vertices_bottom_p.items, num_vertices * sizeof(vector3)); + } + else { + volume = fabs(bottom_polygon_area * prsm->height); + memcpy(wedges_a, prsm->vertices_bottom_p.items, num_vertices * sizeof(vector3)); + memcpy(wedges_b, prsm->vertices_bottom_p.items, num_vertices * sizeof(vector3)); + for (int nv = 0; nv < num_vertices; nv++) { + wedges_b[nv].z = prsm->height; + } + memcpy(wedges_c, prsm->vertices_top_p.items, num_vertices * sizeof(vector3)); + } + for (int nv = 0; nv < num_vertices; nv++) { + int nvp1 = (nv + 1 == num_vertices ? 0 : nv + 1); + volume += get_volume_irregular_triangular_prism(wedges_a[nv], wedges_b[nv], wedges_c[nv], wedges_a[nvp1], wedges_b[nvp1], wedges_c[nvp1]); + } + return volume; + } +} + /***************************************************************/ /***************************************************************/ /***************************************************************/ From 2256149319604c7f289f4ad45ade0d1f31f31078 Mon Sep 17 00:00:00 2001 From: danielwboyce Date: Wed, 22 Jan 2020 18:27:01 -0700 Subject: [PATCH 32/63] Update for memory fix and to print volumes --- utils/geom.c | 2 +- utils/test-prism.c | 7 +++++++ 2 files changed, 8 insertions(+), 1 deletion(-) diff --git a/utils/geom.c b/utils/geom.c index 94c0c29..a275706 100644 --- a/utils/geom.c +++ b/utils/geom.c @@ -2447,7 +2447,7 @@ double get_prism_volume(prism *prsm) { wedges_b = (vector3 *)malloc(num_vertices * sizeof(vector3)); CHECK(wedges_b, "out of memory"); vector3 *wedges_c; - wedges_b = (vector3 *)malloc(num_vertices * sizeof(vector3)); + wedges_c = (vector3 *)malloc(num_vertices * sizeof(vector3)); CHECK(wedges_c, "out of memory"); if (bottom_polygon_area > top_polygon_area) { volume = fabs(top_polygon_area * prsm->height); diff --git a/utils/test-prism.c b/utils/test-prism.c index 05cd517..5842ae0 100644 --- a/utils/test-prism.c +++ b/utils/test-prism.c @@ -489,6 +489,9 @@ int test_sidewall_prisms_to_gnuplot() { prism2gnuplot(square_normal_sidewall_prism, "square_normal_sidewall_gnu_plot.dat"); prism2gnuplot(square_one_degree_sidewall_prism, "square_one_degree_sidewall_gnu_plot.dat"); + ctl_printf("The volume of the square-based prism with a normal sidewall angle is %e\n", geom_object_volume(square_normal_sidewall_geom_object)); + ctl_printf("The volume of the square-based prism with a 1-degree sidewall angle is %e\n", geom_object_volume(square_one_degree_sidewall_geom_object)); + int num_nodes_octagon_c = 16; vector3 nodes_octagon_c[num_nodes_octagon_c]; nodes_octagon_c[0] = make_vector3(114.905, 88.7434, 0.0); @@ -520,6 +523,10 @@ int test_sidewall_prisms_to_gnuplot() { prism2gnuplot(octagon_c_normal_sidewall_prism, "octagon_c_normal_sidewall_gnu_plot.dat"); prism2gnuplot(octagon_c_two_half_degree_sidewall_prism, "octagon_c_two_half_degree_sidewall_gnu_plot.dat"); + ctl_printf("The volume of the prism with the concave octagonal c shape base with a normal sidewall angle is %e\n", geom_object_volume(octagon_c_normal_sidewall_geom_object)); + ctl_printf("The volume of the prism with the concave octagonal c shape base with a 2.5-degree sidewall angle is %e\n", geom_object_volume(octagon_c_two_half_degree_sidewall_geom_object)); + + return 0; } From 31b0ec81bed59c88a5dd28026026c3df66c2d866 Mon Sep 17 00:00:00 2001 From: danielwboyce Date: Sun, 26 Jan 2020 12:17:56 -0700 Subject: [PATCH 33/63] Changed proportions of test geometry. --- utils/test-prism.c | 10 +++++----- 1 file changed, 5 insertions(+), 5 deletions(-) diff --git a/utils/test-prism.c b/utils/test-prism.c index 5842ae0..b639390 100644 --- a/utils/test-prism.c +++ b/utils/test-prism.c @@ -470,12 +470,12 @@ int test_sidewall_prisms_to_gnuplot() { int num_nodes_square = 4; vector3 nodes_square[num_nodes_square]; - nodes_square[0] = make_vector3(-1.0, -1.0, 0.0); - nodes_square[1] = make_vector3(-1.0, 1.0, 0.0); - nodes_square[2] = make_vector3(1.0, 1.0, 0.0); - nodes_square[3] = make_vector3(1.0, -1.0, 0.0); + nodes_square[0] = make_vector3(-10.0, -10.0, 0.0); + nodes_square[1] = make_vector3(-10.0, 10.0, 0.0); + nodes_square[2] = make_vector3(10.0, 10.0, 0.0); + nodes_square[3] = make_vector3(10.0, -10.0, 0.0); - double height_square = 10; + double height_square = 100; vector3 zhat = make_vector3(0, 0, 1); double normal_sidewall = 0; From 2164d7f5975ddbf59368eba2d3ae92b7d51588ca Mon Sep 17 00:00:00 2001 From: danielwboyce Date: Mon, 27 Jan 2020 12:25:36 -0700 Subject: [PATCH 34/63] Removes some unused properties of prism that were created during sidewall development but ended up being unused. --- utils/geom.c | 14 -------------- utils/geom.scm | 2 -- 2 files changed, 16 deletions(-) diff --git a/utils/geom.c b/utils/geom.c index a71c6b6..1c30e5d 100644 --- a/utils/geom.c +++ b/utils/geom.c @@ -2788,20 +2788,6 @@ void init_prism(geometric_object *o) { prsm->vertices_top.items[nv] = prism_coordinate_p2c(prsm, prsm->vertices_top_p.items[nv]); } - prsm->top_polygon_diff_vectors.num_items = num_vertices; - prsm->top_polygon_diff_vectors.items = (vector3 *)malloc(num_vertices * sizeof(vector3)); - CHECK(prsm->top_polygon_diff_vectors.items, "out of memory"); - for (nv = 0; nv < num_vertices; nv++) { - prsm->top_polygon_diff_vectors.items[nv] = prism_vector_p2c(prsm, prsm->top_polygon_diff_vectors_p.items[nv]); - } - - prsm->top_polygon_diff_vectors_scaled.num_items = num_vertices; - prsm->top_polygon_diff_vectors_scaled.items = (vector3 *)malloc(num_vertices * sizeof(vector3)); - CHECK(prsm->top_polygon_diff_vectors_scaled.items, "out of memory"); - for (nv = 0; nv < num_vertices; nv++) { - prsm->top_polygon_diff_vectors_scaled.items[nv] = prism_vector_p2c(prsm, prsm->top_polygon_diff_vectors_scaled_p.items[nv]); - } - // workspace is an internally-stored double-valued array of length num_vertices+2 // that is used by some geometry routines prsm->workspace.num_items = num_vertices + 2; diff --git a/utils/geom.scm b/utils/geom.scm index 2bf6c5d..24c6495 100644 --- a/utils/geom.scm +++ b/utils/geom.scm @@ -133,8 +133,6 @@ (define-property top_polygon_diff_vectors_p '() (make-list-type 'vector3)) (define-property top_polygon_diff_vectors_scaled_p '() (make-list-type 'vector3)) (define-property vertices_top_p '() (make-list-type 'vector3)) - (define-property top_polygon_diff_vectors '() (make-list-type 'vector3)) - (define-property top_polygon_diff_vectors_scaled '() (make-list-type 'vector3)) (define-property vertices_top '() (make-list-type 'vector3)) (define-property centroid (vector3 0 0 0) 'vector3) (define-property workspace '() (make-list-type 'number)) From 60da7fd1949e66f90a5f4248e483a6f6ec125d63 Mon Sep 17 00:00:00 2001 From: danielwboyce Date: Mon, 27 Jan 2020 13:47:49 -0700 Subject: [PATCH 35/63] Split fifth unit test into two separate ones. --- utils/test-prism.c | 27 ++++++++++++++++++++------- 1 file changed, 20 insertions(+), 7 deletions(-) diff --git a/utils/test-prism.c b/utils/test-prism.c index af5c884..165a408 100644 --- a/utils/test-prism.c +++ b/utils/test-prism.c @@ -461,11 +461,11 @@ int test_point_in_polygon(int write_log) { } /************************************************************************/ -/* fifth unit test: saves a prism with normal sidewall angle and a */ -/* prism with the same base polygon with non-normal sidewall angle to */ -/* separate GNU plot files */ +/* fifth unit test: saves a prism with a square base with a normal */ +/* sidewall angle and a prism with the same base polygon with non- */ +/* normal sidewall angle to separate GNU plot files. */ /************************************************************************/ -int test_sidewall_prisms_to_gnuplot() { +int test_square_base_sidewall_prisms_to_gnuplot() { void *m = NULL; int num_nodes_square = 4; @@ -492,6 +492,17 @@ int test_sidewall_prisms_to_gnuplot() { ctl_printf("The volume of the square-based prism with a normal sidewall angle is %e\n", geom_object_volume(square_normal_sidewall_geom_object)); ctl_printf("The volume of the square-based prism with a 1-degree sidewall angle is %e\n", geom_object_volume(square_one_degree_sidewall_geom_object)); + return 0; +} + +/************************************************************************/ +/* sixth unit test: saves a prism with a concave octagonal c-shaped */ +/* base with a normal sidewall angle and a prism with the same base */ +/* polygon with non-normal sidewall angle to separate GNU plot files. */ +/************************************************************************/ +int test_octagon_c_base_sidewall_prisms_to_gnuplot() { + void *m = NULL; + int num_nodes_octagon_c = 16; vector3 nodes_octagon_c[num_nodes_octagon_c]; nodes_octagon_c[0] = make_vector3(114.905, 88.7434, 0.0); @@ -512,7 +523,9 @@ int test_sidewall_prisms_to_gnuplot() { nodes_octagon_c[15] = make_vector3(140.488, 99.3401, 0.0); double height_octagon_c = 127; + vector3 zhat = make_vector3(0, 0, 1); + double normal_sidewall = 0; geometric_object octagon_c_normal_sidewall_geom_object = make_prism(m, nodes_octagon_c, num_nodes_octagon_c, height_octagon_c, zhat, normal_sidewall); prism *octagon_c_normal_sidewall_prism = octagon_c_normal_sidewall_geom_object.subclass.prism_data; @@ -526,7 +539,6 @@ int test_sidewall_prisms_to_gnuplot() { ctl_printf("The volume of the prism with the concave octagonal c shape base with a normal sidewall angle is %e\n", geom_object_volume(octagon_c_normal_sidewall_geom_object)); ctl_printf("The volume of the prism with the concave octagonal c shape base with a 2.5-degree sidewall angle is %e\n", geom_object_volume(octagon_c_two_half_degree_sidewall_geom_object)); - return 0; } @@ -590,9 +602,10 @@ int run_unit_tests() { int num_failed_2 = 0; // test_normal_to_object(the_block, the_prism, NUMLINES, write_log); int num_failed_3 = test_line_segment_intersection(the_block, the_prism, NUMLINES, write_log); int num_failed_4 = test_point_in_polygon(write_log); - int num_failed_5 = test_sidewall_prisms_to_gnuplot(); + int num_failed_5 = test_square_base_sidewall_prisms_to_gnuplot(); + int num_failed_6 = test_octagon_c_base_sidewall_prisms_to_gnuplot(); - return num_failed_1 + num_failed_2 + num_failed_3 + num_failed_4 + num_failed_5; + return num_failed_1 + num_failed_2 + num_failed_3 + num_failed_4 + num_failed_5 + num_failed_6; } /***************************************************************/ From d29e88709e068da8aa26b755b5d304370af2fc51 Mon Sep 17 00:00:00 2001 From: danielwboyce Date: Mon, 27 Jan 2020 15:26:38 -0700 Subject: [PATCH 36/63] * Began restructuring of unit testing of helper functions * Testing of volume calculation --- utils/test-prism.c | 73 ++++++++++++++++++++++++++++++++++++++++++---- 1 file changed, 67 insertions(+), 6 deletions(-) diff --git a/utils/test-prism.c b/utils/test-prism.c index 165a408..bf2815d 100644 --- a/utils/test-prism.c +++ b/utils/test-prism.c @@ -489,9 +489,6 @@ int test_square_base_sidewall_prisms_to_gnuplot() { prism2gnuplot(square_normal_sidewall_prism, "square_normal_sidewall_gnu_plot.dat"); prism2gnuplot(square_one_degree_sidewall_prism, "square_one_degree_sidewall_gnu_plot.dat"); - ctl_printf("The volume of the square-based prism with a normal sidewall angle is %e\n", geom_object_volume(square_normal_sidewall_geom_object)); - ctl_printf("The volume of the square-based prism with a 1-degree sidewall angle is %e\n", geom_object_volume(square_one_degree_sidewall_geom_object)); - return 0; } @@ -536,12 +533,76 @@ int test_octagon_c_base_sidewall_prisms_to_gnuplot() { prism2gnuplot(octagon_c_normal_sidewall_prism, "octagon_c_normal_sidewall_gnu_plot.dat"); prism2gnuplot(octagon_c_two_half_degree_sidewall_prism, "octagon_c_two_half_degree_sidewall_gnu_plot.dat"); - ctl_printf("The volume of the prism with the concave octagonal c shape base with a normal sidewall angle is %e\n", geom_object_volume(octagon_c_normal_sidewall_geom_object)); - ctl_printf("The volume of the prism with the concave octagonal c shape base with a 2.5-degree sidewall angle is %e\n", geom_object_volume(octagon_c_two_half_degree_sidewall_geom_object)); - return 0; } +/************************************************************************/ +/* seventh unit test: test all of geom.c's prism helper functions on a */ +/* prism with a concave octagonal c-shaped base with both a normal */ +/* sidewall angle a 2.5-degree sidewall angle. */ +/************************************************************************/ +int test_helper_functions_on_octagonal_c_prism() { + void *m = NULL; + + int num_nodes_octagon_c = 16; + vector3 nodes_octagon_c[num_nodes_octagon_c]; + nodes_octagon_c[0] = make_vector3(114.905, 88.7434, 0.0); + nodes_octagon_c[1] = make_vector3(88.7434, 114.905, 0.0); + nodes_octagon_c[2] = make_vector3(51.7447, 114.905, 0.0); + nodes_octagon_c[3] = make_vector3(25.5827, 88.7434, 0.0); + nodes_octagon_c[4] = make_vector3(25.5827, 51.7447, 0.0); + nodes_octagon_c[5] = make_vector3(51.7447, 25.5827, 0.0); + nodes_octagon_c[6] = make_vector3(88.7434, 25.5827, 0.0); + nodes_octagon_c[7] = make_vector3(114.905, 51.7447, 0.0); + nodes_octagon_c[8] = make_vector3(140.488, 41.1477, 0.0); + nodes_octagon_c[9] = make_vector3(99.3401, 0.0, 0.0); + nodes_octagon_c[10] = make_vector3(41.1477, 0.0, 0.0); + nodes_octagon_c[11] = make_vector3(0.0, 41.1477, 0.0); + nodes_octagon_c[12] = make_vector3(0.0, 99.3401, 0.0); + nodes_octagon_c[13] = make_vector3(41.1477, 140.488, 0.0); + nodes_octagon_c[14] = make_vector3(99.3401, 140.488, 0.0); + nodes_octagon_c[15] = make_vector3(140.488, 99.3401, 0.0); + + double height_octagon_c = 127; + vector3 zhat = make_vector3(0, 0, 1); + + double normal_sidewall = 0; + geometric_object octagon_c_normal_sidewall_geom_object = make_prism(m, nodes_octagon_c, num_nodes_octagon_c, height_octagon_c, zhat, normal_sidewall); + prism *octagon_c_normal_sidewall_prism = octagon_c_normal_sidewall_geom_object.subclass.prism_data; + + double two_half_degree_sidewall = 2.5 * 2 * K_PI / 360.0; + geometric_object octagon_c_two_half_degree_sidewall_geom_object = make_prism(m, nodes_octagon_c, num_nodes_octagon_c, height_octagon_c, zhat, two_half_degree_sidewall); + prism *octagon_c_two_half_degree_sidewall_prism = octagon_c_two_half_degree_sidewall_geom_object.subclass.prism_data; + + int num_failed_normal = 0; + int num_failed_tapered = 0; + + // test geom_object_volume + double volume_normal_sidewall_freecad = 1082462.27453587; + double volume_normal_sidewall_calculated = geom_object_volume(octagon_c_normal_sidewall_geom_object); + + if (fabs((volume_normal_sidewall_calculated-volume_normal_sidewall_freecad)/volume_normal_sidewall_freecad) > 5e-5) { + num_failed_normal++; + } + + double volume_tapered_sidewall_freecad = 833978.754046812; + double volume_tapered_sidewall_calculated = geom_object_volume(octagon_c_two_half_degree_sidewall_geom_object); + + if (fabs((volume_tapered_sidewall_calculated-volume_tapered_sidewall_freecad)/volume_tapered_sidewall_freecad) > 5e-5) { + num_failed_tapered++; + } + + // test point_in_prism + + // test normal_to_prism + + // test intersect_line_segment_with_prism + + printf("prism helper function testing: %i/4 tests failed with normal sidewall, %i/4 tests failed with tapered sidewall\n", num_failed_normal, num_failed_tapered); + + return num_failed_normal + num_failed_tapered; +} + /***************************************************************/ /* unit tests: create the same parallelepiped two ways (as a */ /* block and as a prism) and verify that geometric primitives */ From 679af4b7d2462f9023afa2257b8029ba45ff026d Mon Sep 17 00:00:00 2001 From: danielwboyce Date: Mon, 27 Jan 2020 15:28:33 -0700 Subject: [PATCH 37/63] Reorganized results string --- utils/test-prism.c | 5 +++-- 1 file changed, 3 insertions(+), 2 deletions(-) diff --git a/utils/test-prism.c b/utils/test-prism.c index bf2815d..865bf18 100644 --- a/utils/test-prism.c +++ b/utils/test-prism.c @@ -598,7 +598,7 @@ int test_helper_functions_on_octagonal_c_prism() { // test intersect_line_segment_with_prism - printf("prism helper function testing: %i/4 tests failed with normal sidewall, %i/4 tests failed with tapered sidewall\n", num_failed_normal, num_failed_tapered); + printf("prism helper function testing: \n\t%i/4 tests failed with normal sidewall\n\t%i/4 tests failed with tapered sidewall\n", num_failed_normal, num_failed_tapered); return num_failed_normal + num_failed_tapered; } @@ -665,8 +665,9 @@ int run_unit_tests() { int num_failed_4 = test_point_in_polygon(write_log); int num_failed_5 = test_square_base_sidewall_prisms_to_gnuplot(); int num_failed_6 = test_octagon_c_base_sidewall_prisms_to_gnuplot(); + int num_failed_7 = test_helper_functions_on_octagonal_c_prism(); - return num_failed_1 + num_failed_2 + num_failed_3 + num_failed_4 + num_failed_5 + num_failed_6; + return num_failed_1 + num_failed_2 + num_failed_3 + num_failed_4 + num_failed_5 + num_failed_6 + num_failed_7; } /***************************************************************/ From 9e6258e1e944d557f62cb7ea9b477065aedc486c Mon Sep 17 00:00:00 2001 From: danielwboyce Date: Mon, 27 Jan 2020 17:43:57 -0700 Subject: [PATCH 38/63] Added some test points, but should probably rethink them. --- utils/test-prism.c | 54 +++++++++++++++++++++++++++++++++++++++++----- 1 file changed, 49 insertions(+), 5 deletions(-) diff --git a/utils/test-prism.c b/utils/test-prism.c index 865bf18..9a04ba4 100644 --- a/utils/test-prism.c +++ b/utils/test-prism.c @@ -542,6 +542,11 @@ int test_octagon_c_base_sidewall_prisms_to_gnuplot() { /* sidewall angle a 2.5-degree sidewall angle. */ /************************************************************************/ int test_helper_functions_on_octagonal_c_prism() { + double relative_error(double actual, double expected) { + return fabs((actual-expected)/actual); + } + double tolerance = 5.0e-5; + void *m = NULL; int num_nodes_octagon_c = 16; @@ -574,31 +579,70 @@ int test_helper_functions_on_octagonal_c_prism() { geometric_object octagon_c_two_half_degree_sidewall_geom_object = make_prism(m, nodes_octagon_c, num_nodes_octagon_c, height_octagon_c, zhat, two_half_degree_sidewall); prism *octagon_c_two_half_degree_sidewall_prism = octagon_c_two_half_degree_sidewall_geom_object.subclass.prism_data; + int num_tests_normal = 0; int num_failed_normal = 0; + int num_tests_tapered = 0; int num_failed_tapered = 0; // test geom_object_volume double volume_normal_sidewall_freecad = 1082462.27453587; double volume_normal_sidewall_calculated = geom_object_volume(octagon_c_normal_sidewall_geom_object); - - if (fabs((volume_normal_sidewall_calculated-volume_normal_sidewall_freecad)/volume_normal_sidewall_freecad) > 5e-5) { + num_tests_normal++; + if (relative_error(volume_normal_sidewall_calculated, volume_normal_sidewall_freecad) > tolerance) { num_failed_normal++; } double volume_tapered_sidewall_freecad = 833978.754046812; double volume_tapered_sidewall_calculated = geom_object_volume(octagon_c_two_half_degree_sidewall_geom_object); - - if (fabs((volume_tapered_sidewall_calculated-volume_tapered_sidewall_freecad)/volume_tapered_sidewall_freecad) > 5e-5) { + num_tests_tapered++; + if (relative_error(volume_tapered_sidewall_calculated, volume_tapered_sidewall_freecad) > tolerance) { num_failed_tapered++; } // test point_in_prism + vector3_list point_in_prism_test_points_normal_sidewall; + point_in_prism_test_points_normal_sidewall.num_items = 6; + point_in_prism_test_points_normal_sidewall.items = (vector3 *)malloc(point_in_prism_test_points_normal_sidewall.num_items * sizeof(vector3)); + point_in_prism_test_points_normal_sidewall.items[0] = make_vector3(140.488, 99.3401, 127.); // failing point, probably from high tolerance in floating-point numbers + point_in_prism_test_points_normal_sidewall.items[1] = make_vector3(140.488, 99.3401, 129.); + point_in_prism_test_points_normal_sidewall.items[2] = make_vector3(141.902, 97.9259, 127.); + point_in_prism_test_points_normal_sidewall.items[3] = make_vector3(142.336, 100.105, 127.); + point_in_prism_test_points_normal_sidewall.items[4] = make_vector3(137.226, 99.9890, 125.); + point_in_prism_test_points_normal_sidewall.items[5] = make_vector3(25.5827, 88.7434, 127.); // failing point, probably from high tolerance in floating-point numbers + point_in_prism_test_points_normal_sidewall.items[6] = make_vector3(25.5827, 88.7434, 129.); + point_in_prism_test_points_normal_sidewall.items[7] = make_vector3(24.1685, 87.3292, 127.); + point_in_prism_test_points_normal_sidewall.items[8] = make_vector3(25.5827, 90.7434, 127.); + point_in_prism_test_points_normal_sidewall.items[9] = make_vector3(26.9969, 88.1576, 125.); + + int point_in_prism_expected_normal_sidewall[point_in_prism_test_points_normal_sidewall.num_items]; + point_in_prism_expected_normal_sidewall[0] = 1; + point_in_prism_expected_normal_sidewall[1] = 0; + point_in_prism_expected_normal_sidewall[2] = 0; + point_in_prism_expected_normal_sidewall[3] = 0; + point_in_prism_expected_normal_sidewall[4] = 1; + point_in_prism_expected_normal_sidewall[5] = 1; + point_in_prism_expected_normal_sidewall[6] = 0; + point_in_prism_expected_normal_sidewall[7] = 1; + point_in_prism_expected_normal_sidewall[8] = 1; + point_in_prism_expected_normal_sidewall[9] = 0; + + int point_in_prism_actual_normal_sidewall[point_in_prism_test_points_normal_sidewall.num_items]; + for (int i = 0; i < point_in_prism_test_points_normal_sidewall.num_items; i++) { + num_tests_normal++; + point_in_prism_actual_normal_sidewall[i] = point_in_fixed_pobjectp(point_in_prism_test_points_normal_sidewall.items[i], &octagon_c_normal_sidewall_geom_object); + } + + for (int i = 0; i < point_in_prism_test_points_normal_sidewall.num_items; i++) { + if (point_in_prism_actual_normal_sidewall[i] != point_in_prism_expected_normal_sidewall[i]) { + num_failed_normal++; + } + } // test normal_to_prism // test intersect_line_segment_with_prism - printf("prism helper function testing: \n\t%i/4 tests failed with normal sidewall\n\t%i/4 tests failed with tapered sidewall\n", num_failed_normal, num_failed_tapered); + printf("prism helper function testing: \n\t%i/11 tests failed with normal sidewall\n\t%i/11 tests failed with tapered sidewall\n", num_failed_normal, num_failed_tapered); return num_failed_normal + num_failed_tapered; } From 61ee5ec7dfc015a3f21d7f617e06789f1f365001 Mon Sep 17 00:00:00 2001 From: danielwboyce Date: Wed, 29 Jan 2020 16:27:05 -0700 Subject: [PATCH 39/63] * Change to intersect_line_with_segment so that fabs(detM)<=0 instead of <0. * Change to status calculation in node_in_or_on_polygon's section checking for points on vertices or edges so that the checking vector is parallel to the edge. --- utils/geom.c | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/utils/geom.c b/utils/geom.c index 1c30e5d..ccb2a42 100644 --- a/utils/geom.c +++ b/utils/geom.c @@ -1975,7 +1975,7 @@ int intersect_line_with_segment(vector3 q0, vector3 q1, vector3 q2, vector3 u, d double dot = q01x * q02x + q01y * q02y; if (fabs(dot) < (1.0 - THRESH) * q01 * q02) return NON_INTERSECTING; - else if (dot < 0.0) { + else if (dot <= 0.0) { *s = 0.0; return IN_SEGMENT; } @@ -2037,7 +2037,7 @@ boolean node_in_or_on_polygon(vector3 q0, vector3 *nodes, int num_nodes, // Is q0 on a vertex or edge? // Transform coordinate system of nodes such that q0 is at 0|0 for (nn = 0; nn < num_nodes; nn++) { - int status = intersect_ray_with_segment(q0, nodes[nn], nodes[(nn + 1) % num_nodes], xAxis, 0); + int status = intersect_ray_with_segment(q0, nodes[nn], nodes[(nn + 1) % num_nodes], unit_vector3(vector3_minus(nodes[(nn + 1) % num_nodes], nodes[nn])), 0); if (status == IN_SEGMENT) { return include_boundaries; } // Find start point which is not on the x axis (from q0) From 22b2703c03acc36f5ea127dd459cb33ffcdda30e Mon Sep 17 00:00:00 2001 From: danielwboyce Date: Thu, 30 Jan 2020 14:41:24 -0700 Subject: [PATCH 40/63] Finalized point_in_prism test points for normal sidewall; all pass. --- utils/test-prism.c | 108 +++++++++++++++++++++++++++++++++------------ 1 file changed, 81 insertions(+), 27 deletions(-) diff --git a/utils/test-prism.c b/utils/test-prism.c index 9a04ba4..488d706 100644 --- a/utils/test-prism.c +++ b/utils/test-prism.c @@ -216,11 +216,11 @@ void prism2gnuplot(prism *prsm, char *filename) { vector3 vcc = prism_coordinate_p2c(prsm, vcp); vector3 vdc = prism_coordinate_p2c(prsm, vdp); - fprintf(f, "%e %e %e \n", vac.x, vac.y, vac.z); - fprintf(f, "%e %e %e \n", vbc.x, vbc.y, vbc.z); - fprintf(f, "%e %e %e \n", vcc.x, vcc.y, vcc.z); - fprintf(f, "%e %e %e \n", vdc.x, vdc.y, vdc.z); - fprintf(f, "%e %e %e \n", vac.x, vac.y, vac.z); + fprintf(f, "%0.16e %0.16e %0.16e \n", vac.x, vac.y, vac.z); + fprintf(f, "%0.16e %0.16e %0.16e \n", vbc.x, vbc.y, vbc.z); + fprintf(f, "%0.16e %0.16e %0.16e \n", vcc.x, vcc.y, vcc.z); + fprintf(f, "%0.16e %0.16e %0.16e \n", vdc.x, vdc.y, vdc.z); + fprintf(f, "%0.16e %0.16e %0.16e \n", vac.x, vac.y, vac.z); fprintf(f, "\n\n"); } fclose(f); @@ -601,30 +601,60 @@ int test_helper_functions_on_octagonal_c_prism() { // test point_in_prism vector3_list point_in_prism_test_points_normal_sidewall; - point_in_prism_test_points_normal_sidewall.num_items = 6; + point_in_prism_test_points_normal_sidewall.num_items = 25; point_in_prism_test_points_normal_sidewall.items = (vector3 *)malloc(point_in_prism_test_points_normal_sidewall.num_items * sizeof(vector3)); - point_in_prism_test_points_normal_sidewall.items[0] = make_vector3(140.488, 99.3401, 127.); // failing point, probably from high tolerance in floating-point numbers - point_in_prism_test_points_normal_sidewall.items[1] = make_vector3(140.488, 99.3401, 129.); - point_in_prism_test_points_normal_sidewall.items[2] = make_vector3(141.902, 97.9259, 127.); - point_in_prism_test_points_normal_sidewall.items[3] = make_vector3(142.336, 100.105, 127.); - point_in_prism_test_points_normal_sidewall.items[4] = make_vector3(137.226, 99.9890, 125.); - point_in_prism_test_points_normal_sidewall.items[5] = make_vector3(25.5827, 88.7434, 127.); // failing point, probably from high tolerance in floating-point numbers - point_in_prism_test_points_normal_sidewall.items[6] = make_vector3(25.5827, 88.7434, 129.); - point_in_prism_test_points_normal_sidewall.items[7] = make_vector3(24.1685, 87.3292, 127.); - point_in_prism_test_points_normal_sidewall.items[8] = make_vector3(25.5827, 90.7434, 127.); - point_in_prism_test_points_normal_sidewall.items[9] = make_vector3(26.9969, 88.1576, 125.); + point_in_prism_test_points_normal_sidewall.items[0] = make_vector3(46.4462, 12.7914, 63.5000); // interior point + point_in_prism_test_points_normal_sidewall.items[1] = make_vector3(127.697, 46.4462, 95.2500); // interior point + point_in_prism_test_points_normal_sidewall.items[2] = make_vector3(70.2439, 0.00000, 31.7500); // point on external side face + point_in_prism_test_points_normal_sidewall.items[3] = make_vector3(101.824, 38.6637, 95.2500); // point on internal side face + point_in_prism_test_points_normal_sidewall.items[4] = make_vector3(19.1870, 49.0955, 127.000); // point on top face + point_in_prism_test_points_normal_sidewall.items[5] = make_vector3(134.092, 96.6909, 0.00000); // point on bottom face + point_in_prism_test_points_normal_sidewall.items[6] = make_vector3(127.6965, 94.04175, 127.0); // edge on top + point_in_prism_test_points_normal_sidewall.items[7] = make_vector3(70.24405, 114.905, 0.0000); // edge on bottom + point_in_prism_test_points_normal_sidewall.items[8] = make_vector3(41.1477, 0.00000, 100.000); // edge on side + point_in_prism_test_points_normal_sidewall.items[9] = make_vector3(140.488, 99.3401, 127.000); // vertex -> corner on top at edge of c + point_in_prism_test_points_normal_sidewall.items[10] = make_vector3(140.488, 99.3401, 129.000); // continuation of edge from vertex + point_in_prism_test_points_normal_sidewall.items[11] = make_vector3(141.902, 97.9259, 127.000); // continuation of edge from vertex + point_in_prism_test_points_normal_sidewall.items[12] = make_vector3(142.336, 100.105, 127.000); // continuation of edge from vertex + point_in_prism_test_points_normal_sidewall.items[13] = make_vector3(137.226, 99.9890, 125.000); // continuation of edge from vertex + point_in_prism_test_points_normal_sidewall.items[14] = make_vector3(25.5827, 88.7434, 127.000); // vertex -> corner on top inside c + point_in_prism_test_points_normal_sidewall.items[15] = make_vector3(25.5827, 88.7434, 129.000); // continuation of edge from vertex + point_in_prism_test_points_normal_sidewall.items[16] = make_vector3(24.1685, 87.3292, 127.000); // continuation of edge from vertex + point_in_prism_test_points_normal_sidewall.items[17] = make_vector3(25.5827, 90.7434, 127.000); // continuation of edge from vertex + point_in_prism_test_points_normal_sidewall.items[18] = make_vector3(26.9969, 88.1576, 125.000); // continuation of edge from vertex + point_in_prism_test_points_normal_sidewall.items[19] = make_vector3(41.1477, 0.00000, 127.000); // vertex -> corner on top outside c + point_in_prism_test_points_normal_sidewall.items[20] = make_vector3(114.905, 51.7447, 0.00000); // vertex -> corner on bottom at edge of c + point_in_prism_test_points_normal_sidewall.items[21] = make_vector3(51.7447, 114.905, 0.00000); // vertex -> corner on bottom inside c + point_in_prism_test_points_normal_sidewall.items[22] = make_vector3(0.00000, 99.3401, 0.00000); // vertex -> corner on bottom outside c + point_in_prism_test_points_normal_sidewall.items[23] = make_vector3(0.00000, 0.00000, 0.00000); // origin + point_in_prism_test_points_normal_sidewall.items[24] = make_vector3(70.2440, 70.2440, 63.5000); // center of the c int point_in_prism_expected_normal_sidewall[point_in_prism_test_points_normal_sidewall.num_items]; - point_in_prism_expected_normal_sidewall[0] = 1; - point_in_prism_expected_normal_sidewall[1] = 0; - point_in_prism_expected_normal_sidewall[2] = 0; - point_in_prism_expected_normal_sidewall[3] = 0; - point_in_prism_expected_normal_sidewall[4] = 1; - point_in_prism_expected_normal_sidewall[5] = 1; - point_in_prism_expected_normal_sidewall[6] = 0; - point_in_prism_expected_normal_sidewall[7] = 1; - point_in_prism_expected_normal_sidewall[8] = 1; - point_in_prism_expected_normal_sidewall[9] = 0; + point_in_prism_expected_normal_sidewall[0] = 1; // interior point + point_in_prism_expected_normal_sidewall[1] = 1; // interior point + point_in_prism_expected_normal_sidewall[2] = 1; // point on external side face + point_in_prism_expected_normal_sidewall[3] = 1; // point on internal side face + point_in_prism_expected_normal_sidewall[4] = 1; // point on top face + point_in_prism_expected_normal_sidewall[5] = 1; // point on bottom face + point_in_prism_expected_normal_sidewall[6] = 1; // edge on top + point_in_prism_expected_normal_sidewall[7] = 1; // edge on bottom + point_in_prism_expected_normal_sidewall[8] = 1; // edge on side + point_in_prism_expected_normal_sidewall[9] = 1; // vertex -> corner on top at edge of c + point_in_prism_expected_normal_sidewall[10] = 0; // continuation of edge from vertex + point_in_prism_expected_normal_sidewall[11] = 0; // continuation of edge from vertex + point_in_prism_expected_normal_sidewall[12] = 0; // continuation of edge from vertex + point_in_prism_expected_normal_sidewall[13] = 1; // continuation of edge from vertex + point_in_prism_expected_normal_sidewall[14] = 1; // vertex -> corner on top inside c + point_in_prism_expected_normal_sidewall[15] = 0; // continuation of edge from vertex + point_in_prism_expected_normal_sidewall[16] = 1; // continuation of edge from vertex + point_in_prism_expected_normal_sidewall[17] = 1; // continuation of edge from vertex + point_in_prism_expected_normal_sidewall[18] = 0; // continuation of edge from vertex + point_in_prism_expected_normal_sidewall[19] = 1; // vertex -> corner on top outside c + point_in_prism_expected_normal_sidewall[20] = 1; // vertex -> corner on bottom at edge of c + point_in_prism_expected_normal_sidewall[21] = 1; // vertex -> corner on bottom inside c + point_in_prism_expected_normal_sidewall[22] = 1; // vertex -> corner on bottom outside c + point_in_prism_expected_normal_sidewall[23] = 0; // origin + point_in_prism_expected_normal_sidewall[24] = 0; // center of the c int point_in_prism_actual_normal_sidewall[point_in_prism_test_points_normal_sidewall.num_items]; for (int i = 0; i < point_in_prism_test_points_normal_sidewall.num_items; i++) { @@ -634,15 +664,39 @@ int test_helper_functions_on_octagonal_c_prism() { for (int i = 0; i < point_in_prism_test_points_normal_sidewall.num_items; i++) { if (point_in_prism_actual_normal_sidewall[i] != point_in_prism_expected_normal_sidewall[i]) { + ctl_printf("At (%f, %f, %f) we expected point_in_fixed_pobjectp to return %i, but instead it returned %i\n", point_in_prism_test_points_normal_sidewall.items[i].x, point_in_prism_test_points_normal_sidewall.items[i].y, point_in_prism_test_points_normal_sidewall.items[i].z, point_in_prism_expected_normal_sidewall[i], point_in_prism_actual_normal_sidewall[i]); num_failed_normal++; } } + /* // test normal_to_prism + vector3_list normal_to_prism_test_points_normal_sidewall; + normal_to_prism_test_points_normal_sidewall.num_items = 1; + normal_to_prism_test_points_normal_sidewall.items = (vector3 *)malloc(normal_to_prism_test_points_normal_sidewall.num_items * sizeof(vector3)); + normal_to_prism_test_points_normal_sidewall.items[0] = make_vector3(114.905, 88.7434, 0.0); + vector3 normal_to_prism_expected_normal_sidewall[normal_to_prism_test_points_normal_sidewall.num_items]; + normal_to_prism_expected_normal_sidewall[0] = make_vector3(0, 0, 0); + + vector3 normal_to_prism_actual_normal_sidewall[normal_to_prism_test_points_normal_sidewall.num_items]; + for (int i = 0; i < normal_to_prism_test_points_normal_sidewall.num_items; i++) { + num_tests_normal++; + normal_to_prism_actual_normal_sidewall[i] = normal_to_fixed_object(normal_to_prism_test_points_normal_sidewall.items[i], octagon_c_normal_sidewall_geom_object); + } + + for (int i = 0; i < normal_to_prism_test_points_normal_sidewall.num_items; i++) { + if (fabs(normal_to_prism_expected_normal_sidewall[i].x - normal_to_prism_actual_normal_sidewall[i].x) > 0.1 + || fabs(normal_to_prism_expected_normal_sidewall[i].y - normal_to_prism_actual_normal_sidewall[i].y) > 0.1 + || fabs(normal_to_prism_expected_normal_sidewall[i].z - normal_to_prism_actual_normal_sidewall[i].z) > 0.1) { + num_failed_normal++; + ctl_printf("The expected normal vector was (%f, %f, %f), but the actual normal vector was (%f, %f, %f\n", normal_to_prism_expected_normal_sidewall[i].x, normal_to_prism_expected_normal_sidewall[i].y, normal_to_prism_expected_normal_sidewall[i].z, normal_to_prism_actual_normal_sidewall[i].x, normal_to_prism_actual_normal_sidewall[i].y, normal_to_prism_actual_normal_sidewall[i].z); + } + } + */ // test intersect_line_segment_with_prism - printf("prism helper function testing: \n\t%i/11 tests failed with normal sidewall\n\t%i/11 tests failed with tapered sidewall\n", num_failed_normal, num_failed_tapered); + printf("prism helper function testing: \n\t%i/%i tests failed with normal sidewall\n\t%i/%i tests failed with tapered sidewall\n", num_failed_normal, num_tests_normal, num_failed_tapered, num_tests_tapered); return num_failed_normal + num_failed_tapered; } From 53585b0d4bccbb02aab2c2d637c464cf21a74c24 Mon Sep 17 00:00:00 2001 From: danielwboyce Date: Thu, 30 Jan 2020 16:54:43 -0700 Subject: [PATCH 41/63] Finalized point_in_prism test points for tapered sidewall; all pass. --- utils/geom.c | 3 +- utils/test-prism.c | 71 +++++++++++++++++++++++++++++++++++++++++++++- 2 files changed, 72 insertions(+), 2 deletions(-) diff --git a/utils/geom.c b/utils/geom.c index ccb2a42..14a52c5 100644 --- a/utils/geom.c +++ b/utils/geom.c @@ -1961,6 +1961,7 @@ vector3 prism_vector_c2p(prism *prsm, vector3 vc) { #define IN_SEGMENT 2 #define ON_RAY 3 int intersect_line_with_segment(vector3 q0, vector3 q1, vector3 q2, vector3 u, double *s) { + if (vector3_nearly_equal(q0, q1, 1e-12) || vector3_nearly_equal(q0, q2, 1e-12)) return IN_SEGMENT; /* ||ux q1x-q2x|| |s| = | q1x-q0x | */ /* ||uy q1y-q2y|| |t| = | q1y-q0y | */ double M00 = u.x, M01 = q1.x - q2.x; @@ -1975,7 +1976,7 @@ int intersect_line_with_segment(vector3 q0, vector3 q1, vector3 q2, vector3 u, d double dot = q01x * q02x + q01y * q02y; if (fabs(dot) < (1.0 - THRESH) * q01 * q02) return NON_INTERSECTING; - else if (dot <= 0.0) { + else if (dot < 0.0) { *s = 0.0; return IN_SEGMENT; } diff --git a/utils/test-prism.c b/utils/test-prism.c index 488d706..545f771 100644 --- a/utils/test-prism.c +++ b/utils/test-prism.c @@ -664,11 +664,80 @@ int test_helper_functions_on_octagonal_c_prism() { for (int i = 0; i < point_in_prism_test_points_normal_sidewall.num_items; i++) { if (point_in_prism_actual_normal_sidewall[i] != point_in_prism_expected_normal_sidewall[i]) { - ctl_printf("At (%f, %f, %f) we expected point_in_fixed_pobjectp to return %i, but instead it returned %i\n", point_in_prism_test_points_normal_sidewall.items[i].x, point_in_prism_test_points_normal_sidewall.items[i].y, point_in_prism_test_points_normal_sidewall.items[i].z, point_in_prism_expected_normal_sidewall[i], point_in_prism_actual_normal_sidewall[i]); + ctl_printf("At (%f, %f, %f) we expected point_in_fixed_pobjectp on the normal sidewall prism to return %i, but instead it returned %i\n", point_in_prism_test_points_normal_sidewall.items[i].x, point_in_prism_test_points_normal_sidewall.items[i].y, point_in_prism_test_points_normal_sidewall.items[i].z, point_in_prism_expected_normal_sidewall[i], point_in_prism_actual_normal_sidewall[i]); num_failed_normal++; } } + vector3_list point_in_prism_test_points_tapered_sidewall; + point_in_prism_test_points_tapered_sidewall.num_items = 25; + point_in_prism_test_points_tapered_sidewall.items = (vector3 *)malloc(point_in_prism_test_points_tapered_sidewall.num_items * sizeof(vector3)); + point_in_prism_test_points_tapered_sidewall.items[0] = make_vector3(46.446200000000005, 12.791350000000001, 63.500000000000000); // interior point + point_in_prism_test_points_tapered_sidewall.items[1] = make_vector3(123.45257948434455, 98.285670515655440, 63.500000000000000); // interior point + point_in_prism_test_points_tapered_sidewall.items[2] = make_vector3(102.72366312425248, 35.642282404302410, 63.500000000000000); // point on external side face + point_in_prism_test_points_tapered_sidewall.items[3] = make_vector3(21.423995187964220, 70.244056207821420, 95.250000000000000); // point on internal side face + point_in_prism_test_points_tapered_sidewall.items[4] = make_vector3(29.618783181268217, 110.86913318128589, 127.00000000000000); // point on top face + point_in_prism_test_points_tapered_sidewall.items[5] = make_vector3(134.09200000000000, 96.690900000000000, 0.0000000000000000); // point on bottom face + point_in_prism_test_points_tapered_sidewall.items[6] = make_vector3(20.037760250618970, 70.244062415642820, 127.00000000000000); // edge on top + point_in_prism_test_points_tapered_sidewall.items[7] = make_vector3(70.244050000000000, 114.90500000000000, 0.0000000000000000); // edge on bottom + point_in_prism_test_points_tapered_sidewall.items[8] = make_vector3(50.596305376632360, 22.810230125309488, 63.500000000000000); // edge on side + point_in_prism_test_points_tapered_sidewall.items[9] = make_vector3(130.69912049055401, 101.28725051332967, 127.00000000000000); // vertex -> corner on top at edge of c // failing + point_in_prism_test_points_tapered_sidewall.items[10] = make_vector3(130.62227962053330, 101.30253528002449, 127.99692620419043); // continuation of edge from vertex + point_in_prism_test_points_tapered_sidewall.items[11] = make_vector3(131.40622727174056, 100.58014373214311, 127.00000000000000); // continuation of edge from vertex + point_in_prism_test_points_tapered_sidewall.items[12] = make_vector3(131.62300162627434, 101.66993007518276, 127.00000000000000); // continuation of edge from vertex + point_in_prism_test_points_tapered_sidewall.items[13] = make_vector3(129.14497344366782, 101.59639296596830, 126.00307379580957); // continuation of edge from vertex + point_in_prism_test_points_tapered_sidewall.items[14] = make_vector3(20.037760250618966, 91.040214078020940, 127.00000000000000); // vertex -> corner on top inside c + point_in_prism_test_points_tapered_sidewall.items[15] = make_vector3(19.994147981293120, 91.058279066765540, 127.99888519167415); // continuation of edge from vertex + point_in_prism_test_points_tapered_sidewall.items[16] = make_vector3(19.330648063809882, 90.333112702498250, 127.00000000000000); // continuation of edge from vertex + point_in_prism_test_points_tapered_sidewall.items[17] = make_vector3(20.037760250618966, 92.040214078020940, 127.00000000000000); // continuation of edge from vertex + point_in_prism_test_points_tapered_sidewall.items[18] = make_vector3(20.788484706753895, 90.729250464799020, 126.00111480832585); // continuation of edge from vertex + point_in_prism_test_points_tapered_sidewall.items[19] = make_vector3(43.444489246735300, 5.5449397493810295, 127.00000000000000); // vertex -> corner on top outside c + point_in_prism_test_points_tapered_sidewall.items[20] = make_vector3(114.90500000000000, 51.744700000000000, 0.0000000000000000); // vertex -> corner on bottom at edge of c + point_in_prism_test_points_tapered_sidewall.items[21] = make_vector3(51.744700000000000, 114.90500000000000, 0.0000000000000000); // vertex -> corner on bottom inside c + point_in_prism_test_points_tapered_sidewall.items[22] = make_vector3(0.0000000000000000, 99.340100000000000, 0.0000000000000000); // vertex -> corner on bottom outside c + point_in_prism_test_points_tapered_sidewall.items[23] = make_vector3(0.0000000000000000, 0.0000000000000000, 0.0000000000000000); // origin + point_in_prism_test_points_tapered_sidewall.items[24] = make_vector3(70.244000000000000, 70.244000000000000, 63.500000000000000); // center of the c + + int point_in_prism_expected_tapered_sidewall[point_in_prism_test_points_tapered_sidewall.num_items]; + point_in_prism_expected_tapered_sidewall[0] = 1; // interior point + point_in_prism_expected_tapered_sidewall[1] = 1; // interior point + point_in_prism_expected_tapered_sidewall[2] = 1; // point on external side face + point_in_prism_expected_tapered_sidewall[3] = 1; // point on internal side face + point_in_prism_expected_tapered_sidewall[4] = 1; // point on top face + point_in_prism_expected_tapered_sidewall[5] = 1; // point on bottom face + point_in_prism_expected_tapered_sidewall[6] = 1; // edge on top + point_in_prism_expected_tapered_sidewall[7] = 1; // edge on bottom + point_in_prism_expected_tapered_sidewall[8] = 1; // edge on side + point_in_prism_expected_tapered_sidewall[9] = 1; // vertex -> corner on top at edge of c + point_in_prism_expected_tapered_sidewall[10] = 0; // continuation of edge from vertex + point_in_prism_expected_tapered_sidewall[11] = 0; // continuation of edge from vertex + point_in_prism_expected_tapered_sidewall[12] = 0; // continuation of edge from vertex + point_in_prism_expected_tapered_sidewall[13] = 1; // continuation of edge from vertex + point_in_prism_expected_tapered_sidewall[14] = 1; // vertex -> corner on top inside c + point_in_prism_expected_tapered_sidewall[15] = 0; // continuation of edge from vertex + point_in_prism_expected_tapered_sidewall[16] = 1; // continuation of edge from vertex + point_in_prism_expected_tapered_sidewall[17] = 1; // continuation of edge from vertex + point_in_prism_expected_tapered_sidewall[18] = 0; // continuation of edge from vertex + point_in_prism_expected_tapered_sidewall[19] = 1; // vertex -> corner on top outside c + point_in_prism_expected_tapered_sidewall[20] = 1; // vertex -> corner on bottom at edge of c + point_in_prism_expected_tapered_sidewall[21] = 1; // vertex -> corner on bottom inside c + point_in_prism_expected_tapered_sidewall[22] = 1; // vertex -> corner on bottom outside c + point_in_prism_expected_tapered_sidewall[23] = 0; // origin + point_in_prism_expected_tapered_sidewall[24] = 0; // center of the c + + int point_in_prism_actual_tapered_sidewall[point_in_prism_test_points_tapered_sidewall.num_items]; + for (int i = 0; i < point_in_prism_test_points_tapered_sidewall.num_items; i++) { + num_tests_tapered++; + point_in_prism_actual_tapered_sidewall[i] = point_in_fixed_pobjectp(point_in_prism_test_points_tapered_sidewall.items[i], &octagon_c_two_half_degree_sidewall_geom_object); + } + + for (int i = 0; i < point_in_prism_test_points_tapered_sidewall.num_items; i++) { + if (point_in_prism_actual_tapered_sidewall[i] != point_in_prism_expected_tapered_sidewall[i]) { + ctl_printf("At (%f, %f, %f) we expected point_in_fixed_pobjectp on the tapered sidewall prism to return %i, but instead it returned %i\n", point_in_prism_test_points_tapered_sidewall.items[i].x, point_in_prism_test_points_tapered_sidewall.items[i].y, point_in_prism_test_points_tapered_sidewall.items[i].z, point_in_prism_expected_tapered_sidewall[i], point_in_prism_actual_tapered_sidewall[i]); + num_failed_tapered++; + } + } + /* // test normal_to_prism vector3_list normal_to_prism_test_points_normal_sidewall; From a48dd78ca63cf080ebf7cf8f2f14b678be45be6d Mon Sep 17 00:00:00 2001 From: danielwboyce Date: Thu, 30 Jan 2020 17:16:02 -0700 Subject: [PATCH 42/63] Slight change to intersect_line_with_segment so that q0 that is within 1e-12 of q1 and q2 automatically passes (if u is parallel to q2-q1) --- utils/geom.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/utils/geom.c b/utils/geom.c index 14a52c5..379720b 100644 --- a/utils/geom.c +++ b/utils/geom.c @@ -1961,7 +1961,6 @@ vector3 prism_vector_c2p(prism *prsm, vector3 vc) { #define IN_SEGMENT 2 #define ON_RAY 3 int intersect_line_with_segment(vector3 q0, vector3 q1, vector3 q2, vector3 u, double *s) { - if (vector3_nearly_equal(q0, q1, 1e-12) || vector3_nearly_equal(q0, q2, 1e-12)) return IN_SEGMENT; /* ||ux q1x-q2x|| |s| = | q1x-q0x | */ /* ||uy q1y-q2y|| |t| = | q1y-q0y | */ double M00 = u.x, M01 = q1.x - q2.x; @@ -1971,6 +1970,7 @@ int intersect_line_with_segment(vector3 q0, vector3 q1, vector3 q2, vector3 u, d double DetM = M00 * M11 - M01 * M10; double L2 = M01 * M01 + M11 * M11; // squared length of edge, used to set length scale if (fabs(DetM) < 1.0e-10 * L2) { // d zero or nearly parallel to edge + if (vector3_nearly_equal(q0, q1, 1e-12) || vector3_nearly_equal(q0, q2, 1e-12)) return IN_SEGMENT; double q01x = q0.x - q1.x, q01y = q0.y - q1.y, q01 = sqrt(q01x * q01x + q01y * q01y); double q02x = q0.x - q2.x, q02y = q0.y - q2.y, q02 = sqrt(q02x * q02x + q02y * q02y); double dot = q01x * q02x + q01y * q02y; From 8642953d6ee4c1b335e93a94dcb82c7013a09bf4 Mon Sep 17 00:00:00 2001 From: danielwboyce Date: Thu, 30 Jan 2020 17:32:16 -0700 Subject: [PATCH 43/63] Shift of relative_error definition location --- utils/test-prism.c | 7 ++++--- 1 file changed, 4 insertions(+), 3 deletions(-) diff --git a/utils/test-prism.c b/utils/test-prism.c index 545f771..c5fd5c1 100644 --- a/utils/test-prism.c +++ b/utils/test-prism.c @@ -541,10 +541,11 @@ int test_octagon_c_base_sidewall_prisms_to_gnuplot() { /* prism with a concave octagonal c-shaped base with both a normal */ /* sidewall angle a 2.5-degree sidewall angle. */ /************************************************************************/ +double relative_error(double actual, double expected) { + return fabs((actual-expected)/actual); +} + int test_helper_functions_on_octagonal_c_prism() { - double relative_error(double actual, double expected) { - return fabs((actual-expected)/actual); - } double tolerance = 5.0e-5; void *m = NULL; From 0e60ea2404955031ccb969eb3f1b657e285b87af Mon Sep 17 00:00:00 2001 From: danielwboyce Date: Sun, 2 Feb 2020 13:03:24 -0700 Subject: [PATCH 44/63] Change to how failing test results are presented --- utils/test-prism.c | 52 ++++++++++++++++++++++++++++++++++++++++------ 1 file changed, 46 insertions(+), 6 deletions(-) diff --git a/utils/test-prism.c b/utils/test-prism.c index c5fd5c1..2680c22 100644 --- a/utils/test-prism.c +++ b/utils/test-prism.c @@ -585,6 +585,8 @@ int test_helper_functions_on_octagonal_c_prism() { int num_tests_tapered = 0; int num_failed_tapered = 0; + printf("prism helper function testing:\n"); + // test geom_object_volume double volume_normal_sidewall_freecad = 1082462.27453587; double volume_normal_sidewall_calculated = geom_object_volume(octagon_c_normal_sidewall_geom_object); @@ -665,7 +667,7 @@ int test_helper_functions_on_octagonal_c_prism() { for (int i = 0; i < point_in_prism_test_points_normal_sidewall.num_items; i++) { if (point_in_prism_actual_normal_sidewall[i] != point_in_prism_expected_normal_sidewall[i]) { - ctl_printf("At (%f, %f, %f) we expected point_in_fixed_pobjectp on the normal sidewall prism to return %i, but instead it returned %i\n", point_in_prism_test_points_normal_sidewall.items[i].x, point_in_prism_test_points_normal_sidewall.items[i].y, point_in_prism_test_points_normal_sidewall.items[i].z, point_in_prism_expected_normal_sidewall[i], point_in_prism_actual_normal_sidewall[i]); + ctl_printf("\tAt (%f, %f, %f) we expected point_in_fixed_pobjectp on the normal sidewall prism to return %i, but instead it returned %i\n", point_in_prism_test_points_normal_sidewall.items[i].x, point_in_prism_test_points_normal_sidewall.items[i].y, point_in_prism_test_points_normal_sidewall.items[i].z, point_in_prism_expected_normal_sidewall[i], point_in_prism_actual_normal_sidewall[i]); num_failed_normal++; } } @@ -734,12 +736,12 @@ int test_helper_functions_on_octagonal_c_prism() { for (int i = 0; i < point_in_prism_test_points_tapered_sidewall.num_items; i++) { if (point_in_prism_actual_tapered_sidewall[i] != point_in_prism_expected_tapered_sidewall[i]) { - ctl_printf("At (%f, %f, %f) we expected point_in_fixed_pobjectp on the tapered sidewall prism to return %i, but instead it returned %i\n", point_in_prism_test_points_tapered_sidewall.items[i].x, point_in_prism_test_points_tapered_sidewall.items[i].y, point_in_prism_test_points_tapered_sidewall.items[i].z, point_in_prism_expected_tapered_sidewall[i], point_in_prism_actual_tapered_sidewall[i]); + ctl_printf("\tAt (%f, %f, %f) we expected point_in_fixed_pobjectp on the tapered sidewall prism to return %i, but instead it returned %i\n", point_in_prism_test_points_tapered_sidewall.items[i].x, point_in_prism_test_points_tapered_sidewall.items[i].y, point_in_prism_test_points_tapered_sidewall.items[i].z, point_in_prism_expected_tapered_sidewall[i], point_in_prism_actual_tapered_sidewall[i]); num_failed_tapered++; } } - /* + // test normal_to_prism vector3_list normal_to_prism_test_points_normal_sidewall; normal_to_prism_test_points_normal_sidewall.num_items = 1; @@ -760,13 +762,51 @@ int test_helper_functions_on_octagonal_c_prism() { || fabs(normal_to_prism_expected_normal_sidewall[i].y - normal_to_prism_actual_normal_sidewall[i].y) > 0.1 || fabs(normal_to_prism_expected_normal_sidewall[i].z - normal_to_prism_actual_normal_sidewall[i].z) > 0.1) { num_failed_normal++; - ctl_printf("The expected normal vector was (%f, %f, %f), but the actual normal vector was (%f, %f, %f\n", normal_to_prism_expected_normal_sidewall[i].x, normal_to_prism_expected_normal_sidewall[i].y, normal_to_prism_expected_normal_sidewall[i].z, normal_to_prism_actual_normal_sidewall[i].x, normal_to_prism_actual_normal_sidewall[i].y, normal_to_prism_actual_normal_sidewall[i].z); + ctl_printf("\tThe expected normal vector was (%f, %f, %f), but the actual\n\t\tnormal vector was (%f, %f, %f\n", normal_to_prism_expected_normal_sidewall[i].x, normal_to_prism_expected_normal_sidewall[i].y, normal_to_prism_expected_normal_sidewall[i].z, normal_to_prism_actual_normal_sidewall[i].x, normal_to_prism_actual_normal_sidewall[i].y, normal_to_prism_actual_normal_sidewall[i].z); } } - */ + // test intersect_line_segment_with_prism + vector3_list intersect_line_with_prism_test_points_normal_sidewall; + intersect_line_with_prism_test_points_normal_sidewall.num_items = 1; + intersect_line_with_prism_test_points_normal_sidewall.items = (vector3 *)malloc(intersect_line_with_prism_test_points_normal_sidewall.num_items * sizeof(vector3)); + intersect_line_with_prism_test_points_normal_sidewall.items[0] = make_vector3(139.252, 96.3552, 123.184); // line crossing [16] to [10] + + vector3 intersect_line_with_prism_test_vectors_normal_sidewall[intersect_line_with_prism_test_points_normal_sidewall.num_items]; + intersect_line_with_prism_test_vectors_normal_sidewall[0] = make_vector3(0.247276, 0.596978, 0.763198); // line crossing [16] to [10] + + double intersect_line_with_prism_expected_normal_sidewall[intersect_line_with_prism_test_points_normal_sidewall.num_items]; + intersect_line_with_prism_expected_normal_sidewall[0] = 2; // line crossing [16] to [10] + + double intersect_line_with_prism_actual_normal_sidewall[intersect_line_with_prism_test_points_normal_sidewall.num_items]; + for (int i = 0; i < intersect_line_with_prism_test_points_normal_sidewall.num_items; i++) { + num_tests_normal++; + vector3 p = intersect_line_with_prism_test_points_normal_sidewall.items[i]; + vector3 d = intersect_line_with_prism_test_vectors_normal_sidewall[i]; + geometric_object o = octagon_c_normal_sidewall_geom_object; + double a = 0; + double b = 300; + intersect_line_with_prism_actual_normal_sidewall[i] = intersect_line_segment_with_object(p, d, o, a, b); + } + + for (int i = 0; i < intersect_line_with_prism_test_points_normal_sidewall.num_items; i++) { + if (intersect_line_with_prism_actual_normal_sidewall[i] != intersect_line_with_prism_expected_normal_sidewall[i]) { + double px = intersect_line_with_prism_test_points_normal_sidewall.items[i].x; + double py = intersect_line_with_prism_test_points_normal_sidewall.items[i].y; + double pz = intersect_line_with_prism_test_points_normal_sidewall.items[i].z; + double dx = intersect_line_with_prism_test_vectors_normal_sidewall[i].x; + double dy = intersect_line_with_prism_test_vectors_normal_sidewall[i].y; + double dz = intersect_line_with_prism_test_vectors_normal_sidewall[i].z; + double expected = intersect_line_with_prism_expected_normal_sidewall[i]; + double actual = intersect_line_with_prism_actual_normal_sidewall[i]; + ctl_printf( + "\tThe line segment emanating from (%f, %f, %f) along s*d,\n\t\twith 0 <= s <= 300, d = (%f, %f, %f), was expected\n\t\tto intersect the prism %f times but instead instersected it %f times.\n", + px, py, pz, dx, dy, dz, expected, actual); + num_failed_normal++; + } + } - printf("prism helper function testing: \n\t%i/%i tests failed with normal sidewall\n\t%i/%i tests failed with tapered sidewall\n", num_failed_normal, num_tests_normal, num_failed_tapered, num_tests_tapered); + printf("\n\tprism helper function testing summary: \n\t\t%i/%i tests failed with normal sidewall\n\t\t%i/%i tests failed with tapered sidewall\n", num_failed_normal, num_tests_normal, num_failed_tapered, num_tests_tapered); return num_failed_normal + num_failed_tapered; } From 23ec85f8b04a405f16ccc826b7b90e77f512b09a Mon Sep 17 00:00:00 2001 From: danielwboyce Date: Mon, 3 Feb 2020 17:56:01 -0700 Subject: [PATCH 45/63] Tuning min_distance_to_prism_roof_or_ceiling for new sidewall scheme --- utils/geom.c | 9 ++++++--- 1 file changed, 6 insertions(+), 3 deletions(-) diff --git a/utils/geom.c b/utils/geom.c index 379720b..e2044f5 100644 --- a/utils/geom.c +++ b/utils/geom.c @@ -2306,13 +2306,16 @@ double min_distance_to_quadrilateral(vector3 p, vector3 o, vector3 v1, vector3 v double min_distance_to_prism_roof_or_ceiling(vector3 pp, prism *prsm, int fc) { int num_vertices = prsm->vertices_bottom_p.num_items; vector3 op = {0.0, 0.0, 0.0}; // origin of floor/ceiling - vector3 *vps; + vector3 vps[num_vertices]; if (fc == 1) { - vps = prsm->vertices_top_p.items; + memcpy(vps, prsm->vertices_top_p.items, num_vertices * sizeof(vector3)); + for (int i = 0; i < num_vertices; i++) { + vps[i].z = 0; + } op.z = prsm->height; } else { - vps = prsm->vertices_bottom_p.items; + memcpy(vps, prsm->vertices_bottom_p.items, num_vertices * sizeof(vector3)); } vector3 zhatp = {0, 0, 1.0}; double s = normal_distance_to_plane(pp, op, vps[0], vps[1], zhatp, 0); From 311318bc5a48368ecdb14b93b1fee4e3683fae67 Mon Sep 17 00:00:00 2001 From: danielwboyce Date: Mon, 3 Feb 2020 17:57:24 -0700 Subject: [PATCH 46/63] Addition of test points for testing normal_to_prism --- utils/test-prism.c | 164 ++++++++++++++++++++++++++++++++++++++++++--- 1 file changed, 154 insertions(+), 10 deletions(-) diff --git a/utils/test-prism.c b/utils/test-prism.c index 2680c22..aa1ee7f 100644 --- a/utils/test-prism.c +++ b/utils/test-prism.c @@ -741,31 +741,175 @@ int test_helper_functions_on_octagonal_c_prism() { } } - // test normal_to_prism vector3_list normal_to_prism_test_points_normal_sidewall; - normal_to_prism_test_points_normal_sidewall.num_items = 1; + normal_to_prism_test_points_normal_sidewall.num_items = 30; normal_to_prism_test_points_normal_sidewall.items = (vector3 *)malloc(normal_to_prism_test_points_normal_sidewall.num_items * sizeof(vector3)); - normal_to_prism_test_points_normal_sidewall.items[0] = make_vector3(114.905, 88.7434, 0.0); + normal_to_prism_test_points_normal_sidewall.items[0] = make_vector3(98.2887, 98.2887, 63.5000); // points around sidewalls + normal_to_prism_test_points_normal_sidewall.items[1] = make_vector3(70.2441, 109.905, 63.5000); + normal_to_prism_test_points_normal_sidewall.items[2] = make_vector3(42.1992, 98.2886, 63.5000); + normal_to_prism_test_points_normal_sidewall.items[3] = make_vector3(30.5827, 70.2441, 63.5000); + normal_to_prism_test_points_normal_sidewall.items[4] = make_vector3(42.1992, 42.1992, 63.5000); + normal_to_prism_test_points_normal_sidewall.items[5] = make_vector3(70.2441, 30.5827, 63.5000); + normal_to_prism_test_points_normal_sidewall.items[6] = make_vector3(98.2886, 42.1992, 63.5000); + normal_to_prism_test_points_normal_sidewall.items[7] = make_vector3(129.610, 51.0656, 63.5000); + normal_to_prism_test_points_normal_sidewall.items[8] = make_vector3(123.450, 17.0383, 63.5000); + normal_to_prism_test_points_normal_sidewall.items[9] = make_vector3(70.2439, -5.0000, 63.5000); + normal_to_prism_test_points_normal_sidewall.items[10] = make_vector3(17.0383, 17.0383, 63.5000); + normal_to_prism_test_points_normal_sidewall.items[11] = make_vector3(-5.0000, 70.2439, 63.5000); + normal_to_prism_test_points_normal_sidewall.items[12] = make_vector3(17.0383, 123.450, 63.5000); + normal_to_prism_test_points_normal_sidewall.items[13] = make_vector3(70.2439, 145.488, 63.5000); + normal_to_prism_test_points_normal_sidewall.items[14] = make_vector3(123.450, 123.450, 63.5000); + normal_to_prism_test_points_normal_sidewall.items[15] = make_vector3(129.610, 89.4223, 63.5000); + normal_to_prism_test_points_normal_sidewall.items[16] = make_vector3(110.869, 110.869, -5.0000); // points off bottom face + normal_to_prism_test_points_normal_sidewall.items[17] = make_vector3(70.2440, 127.697, -5.0000); + normal_to_prism_test_points_normal_sidewall.items[18] = make_vector3(29.6188, 110.869, -5.0000); + normal_to_prism_test_points_normal_sidewall.items[19] = make_vector3(12.7914, 70.2440, -5.0000); + normal_to_prism_test_points_normal_sidewall.items[20] = make_vector3(29.6188, 29.6188, -5.0000); + normal_to_prism_test_points_normal_sidewall.items[21] = make_vector3(70.2440, 12.7914, -5.0000); + normal_to_prism_test_points_normal_sidewall.items[22] = make_vector3(110.869, 29.6188, -5.0000); + // normal_to_prism_test_points_normal_sidewall.items[23] = make_vector3(108.747, 112.991, 132.000); // failing // points off top face + normal_to_prism_test_points_normal_sidewall.items[23] = make_vector3(110.869, 110.869, 132.000); + normal_to_prism_test_points_normal_sidewall.items[24] = make_vector3(70.2440, 127.697, 132.000); // failing + normal_to_prism_test_points_normal_sidewall.items[25] = make_vector3(29.6188, 110.869, 132.000); + normal_to_prism_test_points_normal_sidewall.items[26] = make_vector3(12.7914, 70.2440, 132.000); // failing + normal_to_prism_test_points_normal_sidewall.items[27] = make_vector3(29.6188, 29.6188, 132.000); // failing + normal_to_prism_test_points_normal_sidewall.items[28] = make_vector3(70.2440, 12.7914, 132.000); // failing + normal_to_prism_test_points_normal_sidewall.items[29] = make_vector3(108.747, 27.4968, 132.000); vector3 normal_to_prism_expected_normal_sidewall[normal_to_prism_test_points_normal_sidewall.num_items]; - normal_to_prism_expected_normal_sidewall[0] = make_vector3(0, 0, 0); + normal_to_prism_expected_normal_sidewall[0] = make_vector3(-0.707107, -0.707107, 0.0000000); // points around sidewalls + normal_to_prism_expected_normal_sidewall[1] = make_vector3(0.0000000, -1.000000, 0.0000000); + normal_to_prism_expected_normal_sidewall[2] = make_vector3(0.7071010, -0.707112, 0.0000000); + normal_to_prism_expected_normal_sidewall[3] = make_vector3(1.0000000, 0.0000000, 0.0000000); + normal_to_prism_expected_normal_sidewall[4] = make_vector3(0.7071070, 0.7071070, 0.0000000); + normal_to_prism_expected_normal_sidewall[5] = make_vector3(0.0000000, 1.0000000, 0.0000000); + normal_to_prism_expected_normal_sidewall[6] = make_vector3(-0.707112, 0.7071010, 0.0000000); + normal_to_prism_expected_normal_sidewall[7] = make_vector3(0.3826890, 0.9238770, 0.0000000); + normal_to_prism_expected_normal_sidewall[8] = make_vector3(0.7071050, -0.707108, 0.0000000); + normal_to_prism_expected_normal_sidewall[9] = make_vector3(0.0000000, -1.000000, 0.0000000); + normal_to_prism_expected_normal_sidewall[10] = make_vector3(-0.707107, -0.707107, 0.0000000); + normal_to_prism_expected_normal_sidewall[11] = make_vector3(-1.000000, 0.0000000, 0.0000000); + normal_to_prism_expected_normal_sidewall[12] = make_vector3(-0.707108, 0.7071050, 0.0000000); + normal_to_prism_expected_normal_sidewall[13] = make_vector3(0.0000000, 1.0000000, 0.0000000); + normal_to_prism_expected_normal_sidewall[14] = make_vector3(0.7071070, 0.7071070, 0.0000000); + normal_to_prism_expected_normal_sidewall[15] = make_vector3(0.3826800, -0.923881, 0.0000000); + normal_to_prism_expected_normal_sidewall[16] = make_vector3(0.0000000, 0.0000000, -1.000000); // points off bottom face + normal_to_prism_expected_normal_sidewall[17] = make_vector3(0.0000000, 0.0000000, -1.000000); + normal_to_prism_expected_normal_sidewall[18] = make_vector3(0.0000000, 0.0000000, -1.000000); + normal_to_prism_expected_normal_sidewall[19] = make_vector3(0.0000000, 0.0000000, -1.000000); + normal_to_prism_expected_normal_sidewall[20] = make_vector3(0.0000000, 0.0000000, -1.000000); + normal_to_prism_expected_normal_sidewall[21] = make_vector3(0.0000000, 0.0000000, -1.000000); + normal_to_prism_expected_normal_sidewall[22] = make_vector3(0.0000000, 0.0000000, -1.000000); + normal_to_prism_expected_normal_sidewall[23] = make_vector3(0.0000000, 0.0000000, 1.0000000); // failing // points off top face + normal_to_prism_expected_normal_sidewall[24] = make_vector3(0.0000000, 0.0000000, 1.0000000); // failing + normal_to_prism_expected_normal_sidewall[25] = make_vector3(0.0000000, 0.0000000, 1.0000000); + normal_to_prism_expected_normal_sidewall[26] = make_vector3(0.0000000, 0.0000000, 1.0000000); // failing + normal_to_prism_expected_normal_sidewall[27] = make_vector3(0.0000000, 0.0000000, 1.0000000); // failing + normal_to_prism_expected_normal_sidewall[28] = make_vector3(0.0000000, 0.0000000, 1.0000000); // failing + normal_to_prism_expected_normal_sidewall[29] = make_vector3(0.0000000, 0.0000000, 1.0000000); vector3 normal_to_prism_actual_normal_sidewall[normal_to_prism_test_points_normal_sidewall.num_items]; for (int i = 0; i < normal_to_prism_test_points_normal_sidewall.num_items; i++) { num_tests_normal++; - normal_to_prism_actual_normal_sidewall[i] = normal_to_fixed_object(normal_to_prism_test_points_normal_sidewall.items[i], octagon_c_normal_sidewall_geom_object); + normal_to_prism_actual_normal_sidewall[i] = unit_vector3(normal_to_object(normal_to_prism_test_points_normal_sidewall.items[i], octagon_c_normal_sidewall_geom_object)); } for (int i = 0; i < normal_to_prism_test_points_normal_sidewall.num_items; i++) { - if (fabs(normal_to_prism_expected_normal_sidewall[i].x - normal_to_prism_actual_normal_sidewall[i].x) > 0.1 - || fabs(normal_to_prism_expected_normal_sidewall[i].y - normal_to_prism_actual_normal_sidewall[i].y) > 0.1 - || fabs(normal_to_prism_expected_normal_sidewall[i].z - normal_to_prism_actual_normal_sidewall[i].z) > 0.1) { + if (!vector3_nearly_equal(normal_to_prism_expected_normal_sidewall[i], normal_to_prism_actual_normal_sidewall[i], tolerance) + && !vector3_nearly_equal(normal_to_prism_expected_normal_sidewall[i], vector3_scale(-1, normal_to_prism_actual_normal_sidewall[i]), tolerance)) { num_failed_normal++; - ctl_printf("\tThe expected normal vector was (%f, %f, %f), but the actual\n\t\tnormal vector was (%f, %f, %f\n", normal_to_prism_expected_normal_sidewall[i].x, normal_to_prism_expected_normal_sidewall[i].y, normal_to_prism_expected_normal_sidewall[i].z, normal_to_prism_actual_normal_sidewall[i].x, normal_to_prism_actual_normal_sidewall[i].y, normal_to_prism_actual_normal_sidewall[i].z); + vector3 test_point = normal_to_prism_test_points_normal_sidewall.items[i]; + vector3 expected = normal_to_prism_expected_normal_sidewall[i]; + vector3 actual = normal_to_prism_actual_normal_sidewall[i]; + ctl_printf("\tAt (%f, %f, %f) the expected normal vector was (%f, %f, %f), but the actual\n\t\tnormal vector was (%f, %f, %f\n", test_point.x, test_point.y, test_point.z, expected.x, expected.y, expected.z, actual.x, actual.y, actual.z); } } + vector3_list normal_to_prism_test_points_tapered_sidewall; + normal_to_prism_test_points_tapered_sidewall.num_items = 30; + normal_to_prism_test_points_tapered_sidewall.items = (vector3 *)malloc(normal_to_prism_test_points_tapered_sidewall.num_items * sizeof(vector3)); + normal_to_prism_test_points_tapered_sidewall.items[0] = make_vector3(106.256, 108.378, 63.2819); // points around sidewalls + normal_to_prism_test_points_tapered_sidewall.items[1] = make_vector3(70.2441, 122.673, 63.2819); + normal_to_prism_test_points_tapered_sidewall.items[2] = make_vector3(33.1711, 107.317, 63.2819); + normal_to_prism_test_points_tapered_sidewall.items[3] = make_vector3(17.8150, 70.2441, 63.2819); + normal_to_prism_test_points_tapered_sidewall.items[4] = make_vector3(33.1711, 33.1711, 63.2819); + normal_to_prism_test_points_tapered_sidewall.items[5] = make_vector3(70.2441, 17.8150, 63.2819); + normal_to_prism_test_points_tapered_sidewall.items[6] = make_vector3(106.256, 32.1101, 63.2819); + normal_to_prism_test_points_tapered_sidewall.items[7] = make_vector3(123.663, 39.7093, 63.2819); + normal_to_prism_test_points_tapered_sidewall.items[8] = make_vector3(113.360, 25.0055, 63.2819); + normal_to_prism_test_points_tapered_sidewall.items[9] = make_vector3(70.2439, 7.76771, 63.2819); + normal_to_prism_test_points_tapered_sidewall.items[10] = make_vector3(26.0665, 26.0665, 63.2819); + normal_to_prism_test_points_tapered_sidewall.items[11] = make_vector3(7.76771, 70.2439, 63.2819); + normal_to_prism_test_points_tapered_sidewall.items[12] = make_vector3(26.0665, 114.421, 63.2819); + normal_to_prism_test_points_tapered_sidewall.items[13] = make_vector3(70.2439, 132.720, 63.2819); + normal_to_prism_test_points_tapered_sidewall.items[14] = make_vector3(113.360, 115.482, 63.2819); + normal_to_prism_test_points_tapered_sidewall.items[15] = make_vector3(123.663, 100.779, 63.2819); + normal_to_prism_test_points_tapered_sidewall.items[16] = make_vector3(110.869, 110.869, -5.0000); // points off bottom face + normal_to_prism_test_points_tapered_sidewall.items[17] = make_vector3(70.2440, 127.697, -5.0000); + normal_to_prism_test_points_tapered_sidewall.items[18] = make_vector3(29.6188, 110.869, -5.0000); + normal_to_prism_test_points_tapered_sidewall.items[19] = make_vector3(12.7914, 70.2440, -5.0000); + normal_to_prism_test_points_tapered_sidewall.items[20] = make_vector3(29.6188, 29.6188, -5.0000); + normal_to_prism_test_points_tapered_sidewall.items[21] = make_vector3(70.2440, 12.7914, -5.0000); + normal_to_prism_test_points_tapered_sidewall.items[22] = make_vector3(110.869, 29.6188, -5.0000); + normal_to_prism_test_points_tapered_sidewall.items[23] = make_vector3(108.747, 112.991, 132.000); // points off top face + normal_to_prism_test_points_tapered_sidewall.items[24] = make_vector3(70.2440, 127.697, 132.000); + normal_to_prism_test_points_tapered_sidewall.items[25] = make_vector3(29.6188, 110.869, 132.000); + normal_to_prism_test_points_tapered_sidewall.items[26] = make_vector3(12.7914, 70.2440, 132.000); + normal_to_prism_test_points_tapered_sidewall.items[27] = make_vector3(29.6188, 29.6188, 132.000); + normal_to_prism_test_points_tapered_sidewall.items[28] = make_vector3(70.2440, 12.7914, 132.000); + normal_to_prism_test_points_tapered_sidewall.items[29] = make_vector3(108.747, 27.4968, 132.000); + + vector3 normal_to_prism_expected_tapered_sidewall[normal_to_prism_test_points_tapered_sidewall.num_items]; + normal_to_prism_expected_tapered_sidewall[0] = make_vector3(0.7064340, 0.7064340, -0.0436194); // points off top face + normal_to_prism_expected_tapered_sidewall[1] = make_vector3(0.0000000, 0.9990480, -0.0436194); + normal_to_prism_expected_tapered_sidewall[2] = make_vector3(-0.706428, 0.7064390, -0.0436194); + normal_to_prism_expected_tapered_sidewall[3] = make_vector3(-0.999048, 0.0000000, -0.0436194); + normal_to_prism_expected_tapered_sidewall[4] = make_vector3(-0.706434, -0.706434, -0.0436194); + normal_to_prism_expected_tapered_sidewall[5] = make_vector3(0.0000000, -0.999048, -0.0436194); + normal_to_prism_expected_tapered_sidewall[6] = make_vector3(0.7064390, -0.706428, -0.0436194); + normal_to_prism_expected_tapered_sidewall[7] = make_vector3(-0.382325, -0.922998, -0.0436194); + normal_to_prism_expected_tapered_sidewall[8] = make_vector3(-0.706432, 0.7064350, -0.0436194); + normal_to_prism_expected_tapered_sidewall[9] = make_vector3(0.0000000, 0.9990480, -0.0436194); + normal_to_prism_expected_tapered_sidewall[10] = make_vector3(0.7064340, 0.7064340, -0.0436194); + normal_to_prism_expected_tapered_sidewall[11] = make_vector3(0.9990480, 0.0000000, -0.0436194); + normal_to_prism_expected_tapered_sidewall[12] = make_vector3(0.7064350, -0.706432, -0.0436194); + normal_to_prism_expected_tapered_sidewall[13] = make_vector3(0.0000000, -0.999048, -0.0436194); + normal_to_prism_expected_tapered_sidewall[14] = make_vector3(-0.706434, -0.706434, -0.0436194); + normal_to_prism_expected_tapered_sidewall[15] = make_vector3(-0.382315, 0.9230020, -0.0436194); + normal_to_prism_expected_tapered_sidewall[16] = make_vector3(0.0000000, 0.0000000, -1.000000); // points off bottom face + normal_to_prism_expected_tapered_sidewall[17] = make_vector3(0.0000000, 0.0000000, -1.000000); + normal_to_prism_expected_tapered_sidewall[18] = make_vector3(0.0000000, 0.0000000, -1.000000); + normal_to_prism_expected_tapered_sidewall[19] = make_vector3(0.0000000, 0.0000000, -1.000000); + normal_to_prism_expected_tapered_sidewall[20] = make_vector3(0.0000000, 0.0000000, -1.000000); + normal_to_prism_expected_tapered_sidewall[21] = make_vector3(0.0000000, 0.0000000, -1.000000); + normal_to_prism_expected_tapered_sidewall[22] = make_vector3(0.0000000, 0.0000000, -1.000000); + normal_to_prism_expected_tapered_sidewall[23] = make_vector3(0.0000000, 0.0000000, 1.0000000); // points off top face + normal_to_prism_expected_tapered_sidewall[24] = make_vector3(0.0000000, 0.0000000, 1.0000000); + normal_to_prism_expected_tapered_sidewall[25] = make_vector3(0.0000000, 0.0000000, 1.0000000); + normal_to_prism_expected_tapered_sidewall[26] = make_vector3(0.0000000, 0.0000000, 1.0000000); + normal_to_prism_expected_tapered_sidewall[27] = make_vector3(0.0000000, 0.0000000, 1.0000000); + normal_to_prism_expected_tapered_sidewall[28] = make_vector3(0.0000000, 0.0000000, 1.0000000); + normal_to_prism_expected_tapered_sidewall[29] = make_vector3(0.0000000, 0.0000000, 1.0000000); + + vector3 normal_to_prism_actual_tapered_sidewall[normal_to_prism_test_points_tapered_sidewall.num_items]; + for (int i = 0; i < normal_to_prism_test_points_tapered_sidewall.num_items; i++) { + num_tests_tapered++; + normal_to_prism_actual_tapered_sidewall[i] = unit_vector3(normal_to_object(normal_to_prism_test_points_tapered_sidewall.items[i], octagon_c_two_half_degree_sidewall_geom_object)); + } + + for (int i = 0; i < normal_to_prism_test_points_tapered_sidewall.num_items; i++) { + if (!vector3_nearly_equal(normal_to_prism_expected_tapered_sidewall[i], normal_to_prism_actual_tapered_sidewall[i], tolerance) + && !vector3_nearly_equal(normal_to_prism_expected_tapered_sidewall[i], vector3_scale(-1, normal_to_prism_actual_tapered_sidewall[i]), tolerance)) { + num_failed_tapered++; + vector3 test_point = normal_to_prism_test_points_tapered_sidewall.items[i]; + vector3 expected = normal_to_prism_expected_tapered_sidewall[i]; + vector3 actual = normal_to_prism_actual_tapered_sidewall[i]; + ctl_printf("\tAt (%f, %f, %f) the expected normal vector was (%f, %f, %f), but the actual\n\t\tnormal vector was (%f, %f, %f\n", test_point.x, test_point.y, test_point.z, expected.x, expected.y, expected.z, actual.x, actual.y, actual.z); + } + } + + /* // test intersect_line_segment_with_prism vector3_list intersect_line_with_prism_test_points_normal_sidewall; intersect_line_with_prism_test_points_normal_sidewall.num_items = 1; @@ -805,7 +949,7 @@ int test_helper_functions_on_octagonal_c_prism() { num_failed_normal++; } } - + */ printf("\n\tprism helper function testing summary: \n\t\t%i/%i tests failed with normal sidewall\n\t\t%i/%i tests failed with tapered sidewall\n", num_failed_normal, num_tests_normal, num_failed_tapered, num_tests_tapered); return num_failed_normal + num_failed_tapered; From 6ced328ed8ab36531a4df6ace8e0692b28a21e28 Mon Sep 17 00:00:00 2001 From: danielwboyce Date: Mon, 3 Feb 2020 18:34:13 -0700 Subject: [PATCH 47/63] Removed some extraneous comments --- utils/test-prism.c | 21 ++++++++++----------- 1 file changed, 10 insertions(+), 11 deletions(-) diff --git a/utils/test-prism.c b/utils/test-prism.c index aa1ee7f..d3bc386 100644 --- a/utils/test-prism.c +++ b/utils/test-prism.c @@ -768,13 +768,12 @@ int test_helper_functions_on_octagonal_c_prism() { normal_to_prism_test_points_normal_sidewall.items[20] = make_vector3(29.6188, 29.6188, -5.0000); normal_to_prism_test_points_normal_sidewall.items[21] = make_vector3(70.2440, 12.7914, -5.0000); normal_to_prism_test_points_normal_sidewall.items[22] = make_vector3(110.869, 29.6188, -5.0000); - // normal_to_prism_test_points_normal_sidewall.items[23] = make_vector3(108.747, 112.991, 132.000); // failing // points off top face - normal_to_prism_test_points_normal_sidewall.items[23] = make_vector3(110.869, 110.869, 132.000); - normal_to_prism_test_points_normal_sidewall.items[24] = make_vector3(70.2440, 127.697, 132.000); // failing + normal_to_prism_test_points_normal_sidewall.items[23] = make_vector3(108.747, 112.991, 132.000); // points off top face + normal_to_prism_test_points_normal_sidewall.items[24] = make_vector3(70.2440, 127.697, 132.000); normal_to_prism_test_points_normal_sidewall.items[25] = make_vector3(29.6188, 110.869, 132.000); - normal_to_prism_test_points_normal_sidewall.items[26] = make_vector3(12.7914, 70.2440, 132.000); // failing - normal_to_prism_test_points_normal_sidewall.items[27] = make_vector3(29.6188, 29.6188, 132.000); // failing - normal_to_prism_test_points_normal_sidewall.items[28] = make_vector3(70.2440, 12.7914, 132.000); // failing + normal_to_prism_test_points_normal_sidewall.items[26] = make_vector3(12.7914, 70.2440, 132.000); + normal_to_prism_test_points_normal_sidewall.items[27] = make_vector3(29.6188, 29.6188, 132.000); + normal_to_prism_test_points_normal_sidewall.items[28] = make_vector3(70.2440, 12.7914, 132.000); normal_to_prism_test_points_normal_sidewall.items[29] = make_vector3(108.747, 27.4968, 132.000); vector3 normal_to_prism_expected_normal_sidewall[normal_to_prism_test_points_normal_sidewall.num_items]; @@ -801,12 +800,12 @@ int test_helper_functions_on_octagonal_c_prism() { normal_to_prism_expected_normal_sidewall[20] = make_vector3(0.0000000, 0.0000000, -1.000000); normal_to_prism_expected_normal_sidewall[21] = make_vector3(0.0000000, 0.0000000, -1.000000); normal_to_prism_expected_normal_sidewall[22] = make_vector3(0.0000000, 0.0000000, -1.000000); - normal_to_prism_expected_normal_sidewall[23] = make_vector3(0.0000000, 0.0000000, 1.0000000); // failing // points off top face - normal_to_prism_expected_normal_sidewall[24] = make_vector3(0.0000000, 0.0000000, 1.0000000); // failing + normal_to_prism_expected_normal_sidewall[23] = make_vector3(0.0000000, 0.0000000, 1.0000000); // points off top face + normal_to_prism_expected_normal_sidewall[24] = make_vector3(0.0000000, 0.0000000, 1.0000000); normal_to_prism_expected_normal_sidewall[25] = make_vector3(0.0000000, 0.0000000, 1.0000000); - normal_to_prism_expected_normal_sidewall[26] = make_vector3(0.0000000, 0.0000000, 1.0000000); // failing - normal_to_prism_expected_normal_sidewall[27] = make_vector3(0.0000000, 0.0000000, 1.0000000); // failing - normal_to_prism_expected_normal_sidewall[28] = make_vector3(0.0000000, 0.0000000, 1.0000000); // failing + normal_to_prism_expected_normal_sidewall[26] = make_vector3(0.0000000, 0.0000000, 1.0000000); + normal_to_prism_expected_normal_sidewall[27] = make_vector3(0.0000000, 0.0000000, 1.0000000); + normal_to_prism_expected_normal_sidewall[28] = make_vector3(0.0000000, 0.0000000, 1.0000000); normal_to_prism_expected_normal_sidewall[29] = make_vector3(0.0000000, 0.0000000, 1.0000000); vector3 normal_to_prism_actual_normal_sidewall[normal_to_prism_test_points_normal_sidewall.num_items]; From b6903032312ba33de024c2466e9ee97c00644783 Mon Sep 17 00:00:00 2001 From: danielwboyce Date: Tue, 4 Feb 2020 17:37:15 -0700 Subject: [PATCH 48/63] Draft version of intersect_line_with_prism where the vector equation is solved for the sidewall intersections instead of checking for a 2D intersection --- utils/geom.c | 61 ++++++++++++++++++++++++++++------------------------ 1 file changed, 33 insertions(+), 28 deletions(-) diff --git a/utils/geom.c b/utils/geom.c index e2044f5..575057a 100644 --- a/utils/geom.c +++ b/utils/geom.c @@ -2148,47 +2148,39 @@ static int dcmp(const void *pd1, const void *pd2) { /* the return value is the number of intersections. */ /******************************************************************/ int intersect_line_with_prism(prism *prsm, vector3 pc, vector3 dc, double *slist) { + double tolerance = 1e-8; vector3 pp = prism_coordinate_c2p(prsm, pc); vector3 dp = prism_vector_c2p(prsm, dc); vector3 *vps_bottom = prsm->vertices_bottom_p.items; - vector3 *vps_diff_scaled = prsm->top_polygon_diff_vectors_scaled_p.items; vector3 *vps_top = prsm->vertices_top_p.items; int num_vertices = prsm->vertices_bottom_p.num_items; double height = prsm->height; - vector3 nodes_at_z[num_vertices]; - int nv; - for (nv = 0; nv < num_vertices; nv++) { - nodes_at_z[nv] = vector3_plus(vps_bottom[nv], vector3_scale(pp.z, vps_diff_scaled[nv])); - } - - // use length of first polygon edge as a length scale for judging - // lengths to be small or large - double length_scale = vector3_norm(vector3_minus(nodes_at_z[1], nodes_at_z[0])); - // identify intersections with prism side faces int num_intersections = 0; + int nv; for (nv = 0; nv < num_vertices; nv++) { int nvp1 = nv + 1; if (nvp1 == num_vertices) nvp1 = 0; - // first solve the in-plane portion of the problem: determine the - // intersection of the XY-plane projection of the line with the - // polygon edge between vertices (nv,nv+1). - double s; - int status = intersect_line_with_segment(pp, nodes_at_z[nv], nodes_at_z[nvp1], dp, &s); - if (status == NON_INTERSECTING || status == ON_RAY) continue; - - // OK, we know the XY-plane projection of the line intersects the polygon edge; - // now go back to 3D, ask for the z-coordinate at which the line intersects - // the z-axis extrusion of the edge, and determine whether this point lies - // inside or outside the height of the prism. - double zp_intersect = pp.z + s * dp.z; - double AbsTol = 1.0e-7 * length_scale; - double zp_min = 0.0 - AbsTol; - double zp_max = height + AbsTol; - if ((zp_intersect < zp_min) || (zp_intersect > zp_max)) continue; - + // checks if dp is parallel to the plane of the prism side face under consideration + vector3 v1 = vector3_minus(vps_bottom[nvp1], vps_bottom[nv]); + vector3 v2 = vector3_minus(vps_top[nv], vps_bottom[nv]); + if (fabs(vector3_dot(dp, vector3_cross(v1, v2))) <= tolerance) continue; + + // to find the intersection point pp + s*dp between the line and the + // prism side face, we will solve the vector equation + // pp + s*dp = o + t*v1 + u*v2 + // where o is vps_bottom[nv], v1 is vps_bottom[nvp1]-vps_bottom[nv], + // v2 is vps_top[nv]-vps_bottom[nv], and 0 <= t <= 1, 0 <= u <= 1. + matrix3x3 M; + M.c0 = v1; + M.c1 = v2; + M.c2 = vector3_scale(-1, dp); + vector3 RHS = vector3_minus(dp, vps_bottom[nv]); + vector3 tus = matrix3x3_vector3_mult(matrix3x3_inverse(M), RHS); + if (tus.x < -tolerance || tus.x > 1+tolerance || tus.y < -tolerance || tus.y > 1+tolerance) continue; + double s = tus.z; slist[num_intersections++] = s; } @@ -2203,7 +2195,20 @@ int intersect_line_with_prism(prism *prsm, vector3 pc, vector3 dc, double *slist slist[num_intersections++] = s; } + // sort slist qsort((void *)slist, num_intersections, sizeof(double), dcmp); + // remove duplicates from slist + int num_unique_elements = 1; + double slist_unique[num_vertices+2]; + slist_unique[0] = slist[0]; + for (nv = 1; nv < num_vertices; nv++) { + if (fabs(slist[nv] - slist[nv-1]) > tolerance) { + slist_unique[num_unique_elements] = slist[nv]; + num_unique_elements++; + } + } + slist = slist_unique; + num_intersections = num_unique_elements; return num_intersections; } From fafc4933f289668e6875bcdecaca4b3f9b0639f4 Mon Sep 17 00:00:00 2001 From: danielwboyce Date: Wed, 5 Feb 2020 16:54:00 -0700 Subject: [PATCH 49/63] Typo in RHS definition in intersect_line_with_prism (had dp instead of pp) --- utils/geom.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/utils/geom.c b/utils/geom.c index 575057a..c95c255 100644 --- a/utils/geom.c +++ b/utils/geom.c @@ -2177,7 +2177,7 @@ int intersect_line_with_prism(prism *prsm, vector3 pc, vector3 dc, double *slist M.c0 = v1; M.c1 = v2; M.c2 = vector3_scale(-1, dp); - vector3 RHS = vector3_minus(dp, vps_bottom[nv]); + vector3 RHS = vector3_minus(pp, vps_bottom[nv]); vector3 tus = matrix3x3_vector3_mult(matrix3x3_inverse(M), RHS); if (tus.x < -tolerance || tus.x > 1+tolerance || tus.y < -tolerance || tus.y > 1+tolerance) continue; double s = tus.z; From de626f2f87c60d5984afa4d11b52c0f1e88876b5 Mon Sep 17 00:00:00 2001 From: danielwboyce Date: Wed, 5 Feb 2020 21:35:23 -0700 Subject: [PATCH 50/63] Update to intersect_line_with_prism so that num_intersections is passed correctly (instead of having an off by one error). After running make check 10,000 times, this resulted in unit test 3 failing only 0.38% of the time (that is, over 10,000,000 tested points only 380 yielded incorrect results, which seem to be due to a floating point error). --- utils/geom.c | 27 +++++++++++++++------------ 1 file changed, 15 insertions(+), 12 deletions(-) diff --git a/utils/geom.c b/utils/geom.c index c95c255..ef9c5d4 100644 --- a/utils/geom.c +++ b/utils/geom.c @@ -2195,21 +2195,24 @@ int intersect_line_with_prism(prism *prsm, vector3 pc, vector3 dc, double *slist slist[num_intersections++] = s; } - // sort slist qsort((void *)slist, num_intersections, sizeof(double), dcmp); - // remove duplicates from slist - int num_unique_elements = 1; - double slist_unique[num_vertices+2]; - slist_unique[0] = slist[0]; - for (nv = 1; nv < num_vertices; nv++) { - if (fabs(slist[nv] - slist[nv-1]) > tolerance) { - slist_unique[num_unique_elements] = slist[nv]; - num_unique_elements++; + // if num_intersections is zero then just return that + if (num_intersections == 0) return num_intersections; + else { + // remove duplicates from slist + int num_unique_elements = 1; + double slist_unique[num_vertices+2]; + slist_unique[0] = slist[0]; + for (nv = 1; nv < num_intersections; nv++) { + if (fabs(slist[nv] - slist[nv-1]) > tolerance) { + slist_unique[num_unique_elements] = slist[nv]; + num_unique_elements++; + } } + slist = slist_unique; + num_intersections = num_unique_elements; + return num_intersections; } - slist = slist_unique; - num_intersections = num_unique_elements; - return num_intersections; } /***************************************************************/ From 4dba67414b6850b7d83f1c1b70d22611821014f1 Mon Sep 17 00:00:00 2001 From: danielwboyce Date: Wed, 5 Feb 2020 21:36:11 -0700 Subject: [PATCH 51/63] Commit backing up extraneous unit test. --- utils/test-prism.c | 138 +++++++++++++++++++++++++++++++++++++++++---- 1 file changed, 127 insertions(+), 11 deletions(-) diff --git a/utils/test-prism.c b/utils/test-prism.c index d3bc386..c8a1875 100644 --- a/utils/test-prism.c +++ b/utils/test-prism.c @@ -265,7 +265,7 @@ vector3 standardize(vector3 v) { } /************************************************************************/ -/* first unit test: check inclusion of randomly-generated points */ +/* 1st unit test: check inclusion of randomly-generated points */ /************************************************************************/ int test_point_inclusion(geometric_object the_block, geometric_object the_prism, int num_tests, int write_log) { @@ -300,7 +300,7 @@ int test_point_inclusion(geometric_object the_block, geometric_object the_prism, } /************************************************************************/ -/* second unit test: check calculation of normals to objects */ +/* 2nd unit test: check calculation of normals to objects */ /************************************************************************/ #define PFACE 0.1 int test_normal_to_object(geometric_object the_block, geometric_object the_prism, int num_tests, @@ -338,7 +338,7 @@ int test_normal_to_object(geometric_object the_block, geometric_object the_prism } /************************************************************************/ -/* third unit test: check-line segment intersections */ +/* 3rd unit test: check-line segment intersections */ /************************************************************************/ int test_line_segment_intersection(geometric_object the_block, geometric_object the_prism, int num_tests, int write_log) { @@ -378,7 +378,124 @@ int test_line_segment_intersection(geometric_object the_block, geometric_object } /************************************************************************/ -/* fourth unit test: check of point in polygon test with slanted H */ +/* fourth unit test: running some particular test points that are known */ +/* to be particularly troublesome in test_line_segment_intersection. */ +/************************************************************************/ +/* +int custom_debug() { + void *m = NULL; + int num_nodes = 4; + vector3 nodes[num_nodes]; + nodes[0] = make_vector3(-0.25, -0.5, -0.75); + nodes[1] = make_vector3(0.25, -0.5, -0.75); + nodes[2] = make_vector3(0.25, 0.5, -0.75); + nodes[3] = make_vector3(-0.25, 0.5, -0.75); + double height = 1.5; + vector3 zhat = make_vector3(0, 0, 1); + double sidewall_angle = 0; + + geometric_object the_prism = make_prism(m, nodes, num_nodes, height, zhat, sidewall_angle); + + vector3_list custom_debug_intersections_test_points; + custom_debug_intersections_test_points.num_items = 12; + custom_debug_intersections_test_points.items = (vector3 *)malloc(custom_debug_intersections_test_points.num_items * sizeof(vector3)); + custom_debug_intersections_test_points.items[0] = make_vector3(1.697446e-02, 3.062249e-01, 4.905154e-01); + custom_debug_intersections_test_points.items[1] = make_vector3(2.976338e-03, 2.853139e-02, -3.231677e-02); + custom_debug_intersections_test_points.items[2] = make_vector3(-2.927777e-01, -7.719853e-02, 5.238586e-01); + custom_debug_intersections_test_points.items[3] = make_vector3(4.144918e-01, -3.341994e-01, 6.344019e-01); + custom_debug_intersections_test_points.items[4] = make_vector3(-1.384952e-01, -5.921033e-01, -1.186381e+00); // failing + custom_debug_intersections_test_points.items[5] = make_vector3(4.791191e-03, -4.208515e-01, -6.405487e-01); + custom_debug_intersections_test_points.items[6] = make_vector3(-2.284288e-01, 8.653566e-01, -1.549580e-01); + custom_debug_intersections_test_points.items[7] = make_vector3(-3.231172e-01, 1.423690e-01, -3.185766e-01); // failing + custom_debug_intersections_test_points.items[8] = make_vector3(-4.858779e-02, -4.514021e-01, -6.305032e-01); + custom_debug_intersections_test_points.items[9] = make_vector3(-4.476677e-01, 7.027821e-01, -6.134772e-01); + custom_debug_intersections_test_points.items[10] = make_vector3(-3.604339e-01, 9.245385e-02, -2.974320e-01); + custom_debug_intersections_test_points.items[11] = make_vector3(-2.619019e-01, -5.164794e-01, -1.361271e-01); + + vector3_list custom_debug_intersections_test_vectors; + custom_debug_intersections_test_vectors.num_items = custom_debug_intersections_test_points.num_items; + custom_debug_intersections_test_vectors.items = (vector3 *)malloc(custom_debug_intersections_test_vectors.num_items * sizeof(vector3)); + custom_debug_intersections_test_vectors.items[0] = make_vector3(4.799756e-01, -7.340031e-01, 4.804819e-01); + custom_debug_intersections_test_vectors.items[1] = make_vector3(3.821483e-01, 8.852039e-01, 2.652860e-01); + custom_debug_intersections_test_vectors.items[2] = make_vector3(4.350841e-01, 6.323497e-01, 6.409647e-01); + custom_debug_intersections_test_vectors.items[3] = make_vector3(-8.691933e-01, 4.836753e-01, 1.027673e-01); + custom_debug_intersections_test_vectors.items[4] = make_vector3(-2.124709e-01, 2.241148e-01, 9.511197e-01 ); // failing + custom_debug_intersections_test_vectors.items[5] = make_vector3(-7.657534e-01, 3.103869e-02, 6.423849e-01 ); + custom_debug_intersections_test_vectors.items[6] = make_vector3(5.331027e-01, -8.172830e-01, 2.187464e-01); + custom_debug_intersections_test_vectors.items[7] = make_vector3(2.052464e-01, 9.019452e-01, 3.799588e-01); // failing + custom_debug_intersections_test_vectors.items[8] = make_vector3(6.123326e-01, 5.255650e-01, 5.906186e-01); + custom_debug_intersections_test_vectors.items[9] = make_vector3(9.018752e-01, -3.385689e-01, 2.683135e-01); + custom_debug_intersections_test_vectors.items[10] = make_vector3(6.671782e-01, -7.356403e-01, 1.170753e-01); + custom_debug_intersections_test_vectors.items[11] = make_vector3(5.628490e-01, 8.150067e-01, 1.377139e-01); + + double custom_debug_intersections_a[custom_debug_intersections_test_points.num_items]; + custom_debug_intersections_a[0] = 2.589105e-01; + custom_debug_intersections_a[1] = 4.391680e-02; + custom_debug_intersections_a[2] = 1.231745e-01; + custom_debug_intersections_a[3] = 5.617384e-03; + custom_debug_intersections_a[4] = 4.902939e-01; + custom_debug_intersections_a[5] = 3.006307e-01; + custom_debug_intersections_a[6] = 7.248314e-01; + custom_debug_intersections_a[7] = 1.064971e-01; + custom_debug_intersections_a[8] = 1.288089e-01; + custom_debug_intersections_a[9] = 5.522725e-02; + custom_debug_intersections_a[10] = 2.067135e-01; + custom_debug_intersections_a[11] = 1.582341e-01; + + double custom_debug_intersections_b[custom_debug_intersections_test_points.num_items]; + custom_debug_intersections_b[0] = 8.082756e-01; + custom_debug_intersections_b[1] = 8.526660e-01; + custom_debug_intersections_b[2] = 7.614422e-01; + custom_debug_intersections_b[3] = 8.082797e-01; + custom_debug_intersections_b[4] = 8.399955e-01; + custom_debug_intersections_b[5] = 8.436420e-01; + custom_debug_intersections_b[6] = 9.989410e-01; + custom_debug_intersections_b[7] = 8.725338e-01; + custom_debug_intersections_b[8] = 9.463053e-01; + custom_debug_intersections_b[9] = 9.102767e-01; + custom_debug_intersections_b[10] = 9.281630e-01; + custom_debug_intersections_b[11] = 9.882542e-01; + + double custom_debug_intersections_expected[custom_debug_intersections_test_points.num_items]; + custom_debug_intersections_expected[0] = 2.265841e-01; + custom_debug_intersections_expected[1] = 4.886934e-01; + custom_debug_intersections_expected[2] = 2.296397e-01; + custom_debug_intersections_expected[3] = 5.752460e-01; + custom_debug_intersections_expected[4] = 3.450638e-02; + custom_debug_intersections_expected[5] = 3.210201e-02; + custom_debug_intersections_expected[6] = 1.726108e-01; + custom_debug_intersections_expected[7] = 4.026999e-02; + custom_debug_intersections_expected[8] = 3.588146e-01; + custom_debug_intersections_expected[9] = 1.746355e-01; + custom_debug_intersections_expected[10] = 5.986446e-01; + custom_debug_intersections_expected[11] = 7.512494e-01; + + int num_tests = 0; + int num_failed = 0; + double custom_debug_intersections_actual[custom_debug_intersections_test_points.num_items]; + for (int i = 0; i < custom_debug_intersections_test_points.num_items; i++) { + vector3 p = custom_debug_intersections_test_points.items[i]; + vector3 d = custom_debug_intersections_test_vectors.items[i]; + double a = custom_debug_intersections_a[i]; + double b = custom_debug_intersections_b[i]; + num_tests++; + custom_debug_intersections_actual[i] = intersect_line_segment_with_object(p, d, the_prism, a, b); + } + + for (int i = 0; i < custom_debug_intersections_test_points.num_items; i++) { + double s_expected = custom_debug_intersections_expected[i]; + double s_actual = custom_debug_intersections_actual[i]; + if (fabs(s_expected - s_actual) > 1.0e-5 * fmax(fabs(s_expected), fabs(s_actual))) { + num_failed++; + printf("the point with index %i failed\n", i); + } + } + printf("%i/%i of problematic segments failed\n", num_failed, num_tests); + return num_failed; +} +*/ +/************************************************************************/ +/* 4th unit test: check of point in polygon test with slanted H */ /************************************************************************/ int test_point_in_polygon(int write_log) { // make array of test points that should always pass @@ -461,7 +578,7 @@ int test_point_in_polygon(int write_log) { } /************************************************************************/ -/* fifth unit test: saves a prism with a square base with a normal */ +/* 5th unit test: saves a prism with a square base with a normal */ /* sidewall angle and a prism with the same base polygon with non- */ /* normal sidewall angle to separate GNU plot files. */ /************************************************************************/ @@ -493,7 +610,7 @@ int test_square_base_sidewall_prisms_to_gnuplot() { } /************************************************************************/ -/* sixth unit test: saves a prism with a concave octagonal c-shaped */ +/* 6th unit test: saves a prism with a concave octagonal c-shaped */ /* base with a normal sidewall angle and a prism with the same base */ /* polygon with non-normal sidewall angle to separate GNU plot files. */ /************************************************************************/ @@ -537,7 +654,7 @@ int test_octagon_c_base_sidewall_prisms_to_gnuplot() { } /************************************************************************/ -/* seventh unit test: test all of geom.c's prism helper functions on a */ +/* 7th unit test: test all of geom.c's prism helper functions on a */ /* prism with a concave octagonal c-shaped base with both a normal */ /* sidewall angle a 2.5-degree sidewall angle. */ /************************************************************************/ @@ -907,7 +1024,6 @@ int test_helper_functions_on_octagonal_c_prism() { ctl_printf("\tAt (%f, %f, %f) the expected normal vector was (%f, %f, %f), but the actual\n\t\tnormal vector was (%f, %f, %f\n", test_point.x, test_point.y, test_point.z, expected.x, expected.y, expected.z, actual.x, actual.y, actual.z); } } - /* // test intersect_line_segment_with_prism vector3_list intersect_line_with_prism_test_points_normal_sidewall; @@ -919,7 +1035,7 @@ int test_helper_functions_on_octagonal_c_prism() { intersect_line_with_prism_test_vectors_normal_sidewall[0] = make_vector3(0.247276, 0.596978, 0.763198); // line crossing [16] to [10] double intersect_line_with_prism_expected_normal_sidewall[intersect_line_with_prism_test_points_normal_sidewall.num_items]; - intersect_line_with_prism_expected_normal_sidewall[0] = 2; // line crossing [16] to [10] + intersect_line_with_prism_expected_normal_sidewall[0] = 4; // line crossing [16] to [10] double intersect_line_with_prism_actual_normal_sidewall[intersect_line_with_prism_test_points_normal_sidewall.num_items]; for (int i = 0; i < intersect_line_with_prism_test_points_normal_sidewall.num_items; i++) { @@ -1011,14 +1127,14 @@ int run_unit_tests() { // 20180712 disabling this test because the new implementation of normal_to_object // for prisms is actually more accurate than the implementation for blocks, // although the distinction is only significant in cases where it is irrelevant - int num_failed_2 = 0; // test_normal_to_object(the_block, the_prism, NUMLINES, write_log); + // int num_failed_2 = test_normal_to_object(the_block, the_prism, NUMLINES, write_log); int num_failed_3 = test_line_segment_intersection(the_block, the_prism, NUMLINES, write_log); int num_failed_4 = test_point_in_polygon(write_log); int num_failed_5 = test_square_base_sidewall_prisms_to_gnuplot(); int num_failed_6 = test_octagon_c_base_sidewall_prisms_to_gnuplot(); int num_failed_7 = test_helper_functions_on_octagonal_c_prism(); - return num_failed_1 + num_failed_2 + num_failed_3 + num_failed_4 + num_failed_5 + num_failed_6 + num_failed_7; + return num_failed_1 + num_failed_3 + num_failed_4 + num_failed_5 + num_failed_6 + num_failed_7; } /***************************************************************/ From fa248c02f3b805a7e4b5cec50af328699b16234f Mon Sep 17 00:00:00 2001 From: danielwboyce Date: Wed, 5 Feb 2020 21:36:53 -0700 Subject: [PATCH 52/63] Removing extra unit test. --- utils/test-prism.c | 117 --------------------------------------------- 1 file changed, 117 deletions(-) diff --git a/utils/test-prism.c b/utils/test-prism.c index c8a1875..4d748ba 100644 --- a/utils/test-prism.c +++ b/utils/test-prism.c @@ -377,123 +377,6 @@ int test_line_segment_intersection(geometric_object the_block, geometric_object return num_failed; } -/************************************************************************/ -/* fourth unit test: running some particular test points that are known */ -/* to be particularly troublesome in test_line_segment_intersection. */ -/************************************************************************/ -/* -int custom_debug() { - void *m = NULL; - int num_nodes = 4; - vector3 nodes[num_nodes]; - nodes[0] = make_vector3(-0.25, -0.5, -0.75); - nodes[1] = make_vector3(0.25, -0.5, -0.75); - nodes[2] = make_vector3(0.25, 0.5, -0.75); - nodes[3] = make_vector3(-0.25, 0.5, -0.75); - double height = 1.5; - vector3 zhat = make_vector3(0, 0, 1); - double sidewall_angle = 0; - - geometric_object the_prism = make_prism(m, nodes, num_nodes, height, zhat, sidewall_angle); - - vector3_list custom_debug_intersections_test_points; - custom_debug_intersections_test_points.num_items = 12; - custom_debug_intersections_test_points.items = (vector3 *)malloc(custom_debug_intersections_test_points.num_items * sizeof(vector3)); - custom_debug_intersections_test_points.items[0] = make_vector3(1.697446e-02, 3.062249e-01, 4.905154e-01); - custom_debug_intersections_test_points.items[1] = make_vector3(2.976338e-03, 2.853139e-02, -3.231677e-02); - custom_debug_intersections_test_points.items[2] = make_vector3(-2.927777e-01, -7.719853e-02, 5.238586e-01); - custom_debug_intersections_test_points.items[3] = make_vector3(4.144918e-01, -3.341994e-01, 6.344019e-01); - custom_debug_intersections_test_points.items[4] = make_vector3(-1.384952e-01, -5.921033e-01, -1.186381e+00); // failing - custom_debug_intersections_test_points.items[5] = make_vector3(4.791191e-03, -4.208515e-01, -6.405487e-01); - custom_debug_intersections_test_points.items[6] = make_vector3(-2.284288e-01, 8.653566e-01, -1.549580e-01); - custom_debug_intersections_test_points.items[7] = make_vector3(-3.231172e-01, 1.423690e-01, -3.185766e-01); // failing - custom_debug_intersections_test_points.items[8] = make_vector3(-4.858779e-02, -4.514021e-01, -6.305032e-01); - custom_debug_intersections_test_points.items[9] = make_vector3(-4.476677e-01, 7.027821e-01, -6.134772e-01); - custom_debug_intersections_test_points.items[10] = make_vector3(-3.604339e-01, 9.245385e-02, -2.974320e-01); - custom_debug_intersections_test_points.items[11] = make_vector3(-2.619019e-01, -5.164794e-01, -1.361271e-01); - - vector3_list custom_debug_intersections_test_vectors; - custom_debug_intersections_test_vectors.num_items = custom_debug_intersections_test_points.num_items; - custom_debug_intersections_test_vectors.items = (vector3 *)malloc(custom_debug_intersections_test_vectors.num_items * sizeof(vector3)); - custom_debug_intersections_test_vectors.items[0] = make_vector3(4.799756e-01, -7.340031e-01, 4.804819e-01); - custom_debug_intersections_test_vectors.items[1] = make_vector3(3.821483e-01, 8.852039e-01, 2.652860e-01); - custom_debug_intersections_test_vectors.items[2] = make_vector3(4.350841e-01, 6.323497e-01, 6.409647e-01); - custom_debug_intersections_test_vectors.items[3] = make_vector3(-8.691933e-01, 4.836753e-01, 1.027673e-01); - custom_debug_intersections_test_vectors.items[4] = make_vector3(-2.124709e-01, 2.241148e-01, 9.511197e-01 ); // failing - custom_debug_intersections_test_vectors.items[5] = make_vector3(-7.657534e-01, 3.103869e-02, 6.423849e-01 ); - custom_debug_intersections_test_vectors.items[6] = make_vector3(5.331027e-01, -8.172830e-01, 2.187464e-01); - custom_debug_intersections_test_vectors.items[7] = make_vector3(2.052464e-01, 9.019452e-01, 3.799588e-01); // failing - custom_debug_intersections_test_vectors.items[8] = make_vector3(6.123326e-01, 5.255650e-01, 5.906186e-01); - custom_debug_intersections_test_vectors.items[9] = make_vector3(9.018752e-01, -3.385689e-01, 2.683135e-01); - custom_debug_intersections_test_vectors.items[10] = make_vector3(6.671782e-01, -7.356403e-01, 1.170753e-01); - custom_debug_intersections_test_vectors.items[11] = make_vector3(5.628490e-01, 8.150067e-01, 1.377139e-01); - - double custom_debug_intersections_a[custom_debug_intersections_test_points.num_items]; - custom_debug_intersections_a[0] = 2.589105e-01; - custom_debug_intersections_a[1] = 4.391680e-02; - custom_debug_intersections_a[2] = 1.231745e-01; - custom_debug_intersections_a[3] = 5.617384e-03; - custom_debug_intersections_a[4] = 4.902939e-01; - custom_debug_intersections_a[5] = 3.006307e-01; - custom_debug_intersections_a[6] = 7.248314e-01; - custom_debug_intersections_a[7] = 1.064971e-01; - custom_debug_intersections_a[8] = 1.288089e-01; - custom_debug_intersections_a[9] = 5.522725e-02; - custom_debug_intersections_a[10] = 2.067135e-01; - custom_debug_intersections_a[11] = 1.582341e-01; - - double custom_debug_intersections_b[custom_debug_intersections_test_points.num_items]; - custom_debug_intersections_b[0] = 8.082756e-01; - custom_debug_intersections_b[1] = 8.526660e-01; - custom_debug_intersections_b[2] = 7.614422e-01; - custom_debug_intersections_b[3] = 8.082797e-01; - custom_debug_intersections_b[4] = 8.399955e-01; - custom_debug_intersections_b[5] = 8.436420e-01; - custom_debug_intersections_b[6] = 9.989410e-01; - custom_debug_intersections_b[7] = 8.725338e-01; - custom_debug_intersections_b[8] = 9.463053e-01; - custom_debug_intersections_b[9] = 9.102767e-01; - custom_debug_intersections_b[10] = 9.281630e-01; - custom_debug_intersections_b[11] = 9.882542e-01; - - double custom_debug_intersections_expected[custom_debug_intersections_test_points.num_items]; - custom_debug_intersections_expected[0] = 2.265841e-01; - custom_debug_intersections_expected[1] = 4.886934e-01; - custom_debug_intersections_expected[2] = 2.296397e-01; - custom_debug_intersections_expected[3] = 5.752460e-01; - custom_debug_intersections_expected[4] = 3.450638e-02; - custom_debug_intersections_expected[5] = 3.210201e-02; - custom_debug_intersections_expected[6] = 1.726108e-01; - custom_debug_intersections_expected[7] = 4.026999e-02; - custom_debug_intersections_expected[8] = 3.588146e-01; - custom_debug_intersections_expected[9] = 1.746355e-01; - custom_debug_intersections_expected[10] = 5.986446e-01; - custom_debug_intersections_expected[11] = 7.512494e-01; - - int num_tests = 0; - int num_failed = 0; - double custom_debug_intersections_actual[custom_debug_intersections_test_points.num_items]; - for (int i = 0; i < custom_debug_intersections_test_points.num_items; i++) { - vector3 p = custom_debug_intersections_test_points.items[i]; - vector3 d = custom_debug_intersections_test_vectors.items[i]; - double a = custom_debug_intersections_a[i]; - double b = custom_debug_intersections_b[i]; - num_tests++; - custom_debug_intersections_actual[i] = intersect_line_segment_with_object(p, d, the_prism, a, b); - } - - for (int i = 0; i < custom_debug_intersections_test_points.num_items; i++) { - double s_expected = custom_debug_intersections_expected[i]; - double s_actual = custom_debug_intersections_actual[i]; - if (fabs(s_expected - s_actual) > 1.0e-5 * fmax(fabs(s_expected), fabs(s_actual))) { - num_failed++; - printf("the point with index %i failed\n", i); - } - } - printf("%i/%i of problematic segments failed\n", num_failed, num_tests); - return num_failed; -} -*/ /************************************************************************/ /* 4th unit test: check of point in polygon test with slanted H */ /************************************************************************/ From 9a49056138e8c1fa4ed3fd2f68a614651d0c606c Mon Sep 17 00:00:00 2001 From: danielwboyce Date: Thu, 6 Feb 2020 13:03:51 -0700 Subject: [PATCH 53/63] One test so far in test-prism for intersect_line_segment_with_prism --- utils/geom.c | 2 +- utils/test-prism.c | 29 ++++++++++++++++++----------- 2 files changed, 19 insertions(+), 12 deletions(-) diff --git a/utils/geom.c b/utils/geom.c index ef9c5d4..1c8a91f 100644 --- a/utils/geom.c +++ b/utils/geom.c @@ -2148,7 +2148,7 @@ static int dcmp(const void *pd1, const void *pd2) { /* the return value is the number of intersections. */ /******************************************************************/ int intersect_line_with_prism(prism *prsm, vector3 pc, vector3 dc, double *slist) { - double tolerance = 1e-8; + double tolerance = 1e-4; vector3 pp = prism_coordinate_c2p(prsm, pc); vector3 dp = prism_vector_c2p(prsm, dc); vector3 *vps_bottom = prsm->vertices_bottom_p.items; diff --git a/utils/test-prism.c b/utils/test-prism.c index 4d748ba..037cde6 100644 --- a/utils/test-prism.c +++ b/utils/test-prism.c @@ -907,18 +907,25 @@ int test_helper_functions_on_octagonal_c_prism() { ctl_printf("\tAt (%f, %f, %f) the expected normal vector was (%f, %f, %f), but the actual\n\t\tnormal vector was (%f, %f, %f\n", test_point.x, test_point.y, test_point.z, expected.x, expected.y, expected.z, actual.x, actual.y, actual.z); } } - /* + // test intersect_line_segment_with_prism vector3_list intersect_line_with_prism_test_points_normal_sidewall; intersect_line_with_prism_test_points_normal_sidewall.num_items = 1; intersect_line_with_prism_test_points_normal_sidewall.items = (vector3 *)malloc(intersect_line_with_prism_test_points_normal_sidewall.num_items * sizeof(vector3)); - intersect_line_with_prism_test_points_normal_sidewall.items[0] = make_vector3(139.252, 96.3552, 123.184); // line crossing [16] to [10] + intersect_line_with_prism_test_points_normal_sidewall.items[0] = make_vector3(141.724, 102.325, 130.816); // line crossing [16] to [10] + intersect_line_with_prism_test_points_normal_sidewall.items[1] = make_vector3(141.724, 102.325, 130.816); // line crossing [16] to [10] vector3 intersect_line_with_prism_test_vectors_normal_sidewall[intersect_line_with_prism_test_points_normal_sidewall.num_items]; - intersect_line_with_prism_test_vectors_normal_sidewall[0] = make_vector3(0.247276, 0.596978, 0.763198); // line crossing [16] to [10] + intersect_line_with_prism_test_vectors_normal_sidewall[0] = make_vector3(-0.247276, -0.596978, -0.763198); // line crossing [16] to [10] double intersect_line_with_prism_expected_normal_sidewall[intersect_line_with_prism_test_points_normal_sidewall.num_items]; - intersect_line_with_prism_expected_normal_sidewall[0] = 4; // line crossing [16] to [10] + intersect_line_with_prism_expected_normal_sidewall[0] = 83.20275844; // line crossing [16] to [10] + + double intersect_line_with_prism_a_normal_sidewall[intersect_line_with_prism_test_points_normal_sidewall.num_items]; + intersect_line_with_prism_a_normal_sidewall[0] = 0; + + double intersect_line_with_prism_b_normal_sidewall[intersect_line_with_prism_test_points_normal_sidewall.num_items]; + intersect_line_with_prism_b_normal_sidewall[0] = 150; double intersect_line_with_prism_actual_normal_sidewall[intersect_line_with_prism_test_points_normal_sidewall.num_items]; for (int i = 0; i < intersect_line_with_prism_test_points_normal_sidewall.num_items; i++) { @@ -926,28 +933,28 @@ int test_helper_functions_on_octagonal_c_prism() { vector3 p = intersect_line_with_prism_test_points_normal_sidewall.items[i]; vector3 d = intersect_line_with_prism_test_vectors_normal_sidewall[i]; geometric_object o = octagon_c_normal_sidewall_geom_object; - double a = 0; - double b = 300; + double a = intersect_line_with_prism_a_normal_sidewall[i]; + double b = intersect_line_with_prism_b_normal_sidewall[i]; intersect_line_with_prism_actual_normal_sidewall[i] = intersect_line_segment_with_object(p, d, o, a, b); } for (int i = 0; i < intersect_line_with_prism_test_points_normal_sidewall.num_items; i++) { - if (intersect_line_with_prism_actual_normal_sidewall[i] != intersect_line_with_prism_expected_normal_sidewall[i]) { + double actual = intersect_line_with_prism_actual_normal_sidewall[i]; + double expected = intersect_line_with_prism_expected_normal_sidewall[i]; + if (fabs(fabs(actual)-fabs(expected)) > tolerance * fmax(fabs(actual), fabs(expected))) { double px = intersect_line_with_prism_test_points_normal_sidewall.items[i].x; double py = intersect_line_with_prism_test_points_normal_sidewall.items[i].y; double pz = intersect_line_with_prism_test_points_normal_sidewall.items[i].z; double dx = intersect_line_with_prism_test_vectors_normal_sidewall[i].x; double dy = intersect_line_with_prism_test_vectors_normal_sidewall[i].y; double dz = intersect_line_with_prism_test_vectors_normal_sidewall[i].z; - double expected = intersect_line_with_prism_expected_normal_sidewall[i]; - double actual = intersect_line_with_prism_actual_normal_sidewall[i]; ctl_printf( - "\tThe line segment emanating from (%f, %f, %f) along s*d,\n\t\twith 0 <= s <= 300, d = (%f, %f, %f), was expected\n\t\tto intersect the prism %f times but instead instersected it %f times.\n", + "\tThe line segment emanating from (%f, %f, %f) along s*d,\n\t\twith 0 <= s <= 300, d = (%f, %f, %f), was expected\n\t\tto have intersection length %f but instead had %f.\n", px, py, pz, dx, dy, dz, expected, actual); num_failed_normal++; } } - */ + printf("\n\tprism helper function testing summary: \n\t\t%i/%i tests failed with normal sidewall\n\t\t%i/%i tests failed with tapered sidewall\n", num_failed_normal, num_tests_normal, num_failed_tapered, num_tests_tapered); return num_failed_normal + num_failed_tapered; From 394b9b93370a0e5b3950ae460a8aa02726119dde Mon Sep 17 00:00:00 2001 From: danielwboyce Date: Thu, 6 Feb 2020 13:04:18 -0700 Subject: [PATCH 54/63] typo --- utils/test-prism.c | 1 - 1 file changed, 1 deletion(-) diff --git a/utils/test-prism.c b/utils/test-prism.c index 037cde6..4b696d5 100644 --- a/utils/test-prism.c +++ b/utils/test-prism.c @@ -913,7 +913,6 @@ int test_helper_functions_on_octagonal_c_prism() { intersect_line_with_prism_test_points_normal_sidewall.num_items = 1; intersect_line_with_prism_test_points_normal_sidewall.items = (vector3 *)malloc(intersect_line_with_prism_test_points_normal_sidewall.num_items * sizeof(vector3)); intersect_line_with_prism_test_points_normal_sidewall.items[0] = make_vector3(141.724, 102.325, 130.816); // line crossing [16] to [10] - intersect_line_with_prism_test_points_normal_sidewall.items[1] = make_vector3(141.724, 102.325, 130.816); // line crossing [16] to [10] vector3 intersect_line_with_prism_test_vectors_normal_sidewall[intersect_line_with_prism_test_points_normal_sidewall.num_items]; intersect_line_with_prism_test_vectors_normal_sidewall[0] = make_vector3(-0.247276, -0.596978, -0.763198); // line crossing [16] to [10] From 6050f55b3e54b2b3eedc2884012a8a5c136adc34 Mon Sep 17 00:00:00 2001 From: danielwboyce Date: Thu, 6 Feb 2020 21:28:50 -0700 Subject: [PATCH 55/63] addition of more tests --- utils/geom.c | 10 ++++--- utils/test-prism.c | 71 ++++++++++++++++++++++++++++++++++++++++------ 2 files changed, 69 insertions(+), 12 deletions(-) diff --git a/utils/geom.c b/utils/geom.c index 1c8a91f..f6aa7b5 100644 --- a/utils/geom.c +++ b/utils/geom.c @@ -2148,7 +2148,6 @@ static int dcmp(const void *pd1, const void *pd2) { /* the return value is the number of intersections. */ /******************************************************************/ int intersect_line_with_prism(prism *prsm, vector3 pc, vector3 dc, double *slist) { - double tolerance = 1e-4; vector3 pp = prism_coordinate_c2p(prsm, pc); vector3 dp = prism_vector_c2p(prsm, dc); vector3 *vps_bottom = prsm->vertices_bottom_p.items; @@ -2157,6 +2156,7 @@ int intersect_line_with_prism(prism *prsm, vector3 pc, vector3 dc, double *slist double height = prsm->height; // identify intersections with prism side faces + double tus_tolerance = 1e-8; int num_intersections = 0; int nv; for (nv = 0; nv < num_vertices; nv++) { @@ -2166,7 +2166,8 @@ int intersect_line_with_prism(prism *prsm, vector3 pc, vector3 dc, double *slist // checks if dp is parallel to the plane of the prism side face under consideration vector3 v1 = vector3_minus(vps_bottom[nvp1], vps_bottom[nv]); vector3 v2 = vector3_minus(vps_top[nv], vps_bottom[nv]); - if (fabs(vector3_dot(dp, vector3_cross(v1, v2))) <= tolerance) continue; + double dot_tolerance = 1e-6; + if (fabs(vector3_dot(dp, vector3_cross(v1, v2))) <= dot_tolerance) continue; // to find the intersection point pp + s*dp between the line and the // prism side face, we will solve the vector equation @@ -2179,7 +2180,7 @@ int intersect_line_with_prism(prism *prsm, vector3 pc, vector3 dc, double *slist M.c2 = vector3_scale(-1, dp); vector3 RHS = vector3_minus(pp, vps_bottom[nv]); vector3 tus = matrix3x3_vector3_mult(matrix3x3_inverse(M), RHS); - if (tus.x < -tolerance || tus.x > 1+tolerance || tus.y < -tolerance || tus.y > 1+tolerance) continue; + if (tus.x < -tus_tolerance || tus.x > 1+tus_tolerance || tus.y < -tus_tolerance || tus.y > 1+tus_tolerance) continue; double s = tus.z; slist[num_intersections++] = s; } @@ -2200,11 +2201,12 @@ int intersect_line_with_prism(prism *prsm, vector3 pc, vector3 dc, double *slist if (num_intersections == 0) return num_intersections; else { // remove duplicates from slist + double duplicate_tolerance = 1e-3; int num_unique_elements = 1; double slist_unique[num_vertices+2]; slist_unique[0] = slist[0]; for (nv = 1; nv < num_intersections; nv++) { - if (fabs(slist[nv] - slist[nv-1]) > tolerance) { + if (fabs(slist[nv] - slist[nv-1]) > duplicate_tolerance*fabs(slist[nv])) { slist_unique[num_unique_elements] = slist[nv]; num_unique_elements++; } diff --git a/utils/test-prism.c b/utils/test-prism.c index 4b696d5..1144abf 100644 --- a/utils/test-prism.c +++ b/utils/test-prism.c @@ -910,21 +910,31 @@ int test_helper_functions_on_octagonal_c_prism() { // test intersect_line_segment_with_prism vector3_list intersect_line_with_prism_test_points_normal_sidewall; - intersect_line_with_prism_test_points_normal_sidewall.num_items = 1; + intersect_line_with_prism_test_points_normal_sidewall.num_items = 3; intersect_line_with_prism_test_points_normal_sidewall.items = (vector3 *)malloc(intersect_line_with_prism_test_points_normal_sidewall.num_items * sizeof(vector3)); - intersect_line_with_prism_test_points_normal_sidewall.items[0] = make_vector3(141.724, 102.325, 130.816); // line crossing [16] to [10] + intersect_line_with_prism_test_points_normal_sidewall.items[0] = make_vector3(100.809, 144.033, 130.205); // line crossing top[15] to bottom[11] + intersect_line_with_prism_test_points_normal_sidewall.items[1] = make_vector3(17.0383, 123.450, 63.5000); // line crossing midpoint 13-14 face to midpoint 9-10 face + intersect_line_with_prism_test_points_normal_sidewall.items[2] = make_vector3(17.0383, 123.450, 63.5000); // line crossing midpoint 13-14 face to midpoint 9-10 face vector3 intersect_line_with_prism_test_vectors_normal_sidewall[intersect_line_with_prism_test_points_normal_sidewall.num_items]; - intersect_line_with_prism_test_vectors_normal_sidewall[0] = make_vector3(-0.247276, -0.596978, -0.763198); // line crossing [16] to [10] - - double intersect_line_with_prism_expected_normal_sidewall[intersect_line_with_prism_test_points_normal_sidewall.num_items]; - intersect_line_with_prism_expected_normal_sidewall[0] = 83.20275844; // line crossing [16] to [10] + intersect_line_with_prism_test_vectors_normal_sidewall[0] = make_vector3(-0.29372, -0.709099, -0.64102); // line crossing top[15] to bottom[11] + intersect_line_with_prism_test_vectors_normal_sidewall[1] = make_vector3(0.707107, -0.707107, 0.000000); // line crossing midpoint 13-14 face to midpoint 9-10 face + intersect_line_with_prism_test_vectors_normal_sidewall[2] = make_vector3(0.707107, -0.707107, 0.000000); // line crossing midpoint 13-14 face to midpoint 9-10 face double intersect_line_with_prism_a_normal_sidewall[intersect_line_with_prism_test_points_normal_sidewall.num_items]; - intersect_line_with_prism_a_normal_sidewall[0] = 0; + intersect_line_with_prism_a_normal_sidewall[0] = 0; // line crossing top[15] to bottom[11] + intersect_line_with_prism_a_normal_sidewall[1] = 0; // line crossing midpoint 13-14 face to midpoint 9-10 face + intersect_line_with_prism_a_normal_sidewall[2] = 100; // line crossing midpoint 13-14 face to midpoint 9-10 face double intersect_line_with_prism_b_normal_sidewall[intersect_line_with_prism_test_points_normal_sidewall.num_items]; - intersect_line_with_prism_b_normal_sidewall[0] = 150; + intersect_line_with_prism_b_normal_sidewall[0] = 150; // line crossing top[15] to bottom[11] + intersect_line_with_prism_b_normal_sidewall[1] = 100; // line crossing midpoint 13-14 face to midpoint 9-10 face + intersect_line_with_prism_b_normal_sidewall[2] = 150; // line crossing midpoint 13-14 face to midpoint 9-10 face + + double intersect_line_with_prism_expected_normal_sidewall[intersect_line_with_prism_test_points_normal_sidewall.num_items]; + intersect_line_with_prism_expected_normal_sidewall[0] = 36.07816398; // line crossing top[15] to bottom[11] + intersect_line_with_prism_expected_normal_sidewall[1] = 25.58291121; // line crossing midpoint 13-14 face to midpoint 9-10 face + intersect_line_with_prism_expected_normal_sidewall[2] = 25.58291120; // line crossing midpoint 13-14 face to midpoint 9-10 face double intersect_line_with_prism_actual_normal_sidewall[intersect_line_with_prism_test_points_normal_sidewall.num_items]; for (int i = 0; i < intersect_line_with_prism_test_points_normal_sidewall.num_items; i++) { @@ -954,6 +964,51 @@ int test_helper_functions_on_octagonal_c_prism() { } } + vector3_list intersect_line_with_prism_test_points_tapered_sidewall; + intersect_line_with_prism_test_points_tapered_sidewall.num_items = 1; + intersect_line_with_prism_test_points_tapered_sidewall.items = (vector3 *)malloc(intersect_line_with_prism_test_points_tapered_sidewall.num_items * sizeof(vector3)); + intersect_line_with_prism_test_points_tapered_sidewall.items[0] = make_vector3(98.4872, 138.429, 130.281); // line crossing top[15] to bottom[11] + + vector3 intersect_line_with_prism_test_vectors_tapered_sidewall[intersect_line_with_prism_test_points_tapered_sidewall.num_items]; + intersect_line_with_prism_test_vectors_tapered_sidewall[0] = make_vector3(-0.288786, -0.697187, -0.656149); // line crossing top[15] to bottom[11] + + double intersect_line_with_prism_expected_tapered_sidewall[intersect_line_with_prism_test_points_tapered_sidewall.num_items]; + intersect_line_with_prism_expected_tapered_sidewall[0] = 21.67860775; // line crossing top[15] to bottom[11] + + double intersect_line_with_prism_a_tapered_sidewall[intersect_line_with_prism_test_points_tapered_sidewall.num_items]; + intersect_line_with_prism_a_tapered_sidewall[0] = 0; // line crossing top[15] to bottom[11] + + double intersect_line_with_prism_b_tapered_sidewall[intersect_line_with_prism_test_points_tapered_sidewall.num_items]; + intersect_line_with_prism_b_tapered_sidewall[0] = 150; // line crossing top[15] to bottom[11] + + double intersect_line_with_prism_actual_tapered_sidewall[intersect_line_with_prism_test_points_tapered_sidewall.num_items]; + for (int i = 0; i < intersect_line_with_prism_test_points_tapered_sidewall.num_items; i++) { + num_tests_tapered++; + vector3 p = intersect_line_with_prism_test_points_tapered_sidewall.items[i]; + vector3 d = intersect_line_with_prism_test_vectors_tapered_sidewall[i]; + geometric_object o = octagon_c_two_half_degree_sidewall_geom_object; + double a = intersect_line_with_prism_a_tapered_sidewall[i]; + double b = intersect_line_with_prism_b_tapered_sidewall[i]; + intersect_line_with_prism_actual_tapered_sidewall[i] = intersect_line_segment_with_object(p, d, o, a, b); + } + + for (int i = 0; i < intersect_line_with_prism_test_points_tapered_sidewall.num_items; i++) { + double actual = intersect_line_with_prism_actual_tapered_sidewall[i]; + double expected = intersect_line_with_prism_expected_tapered_sidewall[i]; + if (fabs(fabs(actual)-fabs(expected)) > tolerance * fmax(fabs(actual), fabs(expected))) { + double px = intersect_line_with_prism_test_points_tapered_sidewall.items[i].x; + double py = intersect_line_with_prism_test_points_tapered_sidewall.items[i].y; + double pz = intersect_line_with_prism_test_points_tapered_sidewall.items[i].z; + double dx = intersect_line_with_prism_test_vectors_tapered_sidewall[i].x; + double dy = intersect_line_with_prism_test_vectors_tapered_sidewall[i].y; + double dz = intersect_line_with_prism_test_vectors_tapered_sidewall[i].z; + ctl_printf( + "\tThe line segment emanating from (%f, %f, %f) along s*d,\n\t\twith 0 <= s <= 300, d = (%f, %f, %f), was expected\n\t\tto have intersection length %f but instead had %f.\n", + px, py, pz, dx, dy, dz, expected, actual); + num_failed_tapered++; + } + } + printf("\n\tprism helper function testing summary: \n\t\t%i/%i tests failed with normal sidewall\n\t\t%i/%i tests failed with tapered sidewall\n", num_failed_normal, num_tests_normal, num_failed_tapered, num_tests_tapered); return num_failed_normal + num_failed_tapered; From b645db67249f43a129dfb4f0c5ca508465807202 Mon Sep 17 00:00:00 2001 From: danielwboyce Date: Sun, 9 Feb 2020 16:35:15 -0700 Subject: [PATCH 56/63] Additional of final test points, which now all pass. --- utils/test-prism.c | 88 +++++++++++++++++++++++++++++++++++++++++----- 1 file changed, 79 insertions(+), 9 deletions(-) diff --git a/utils/test-prism.c b/utils/test-prism.c index 1144abf..f192ad6 100644 --- a/utils/test-prism.c +++ b/utils/test-prism.c @@ -910,31 +910,61 @@ int test_helper_functions_on_octagonal_c_prism() { // test intersect_line_segment_with_prism vector3_list intersect_line_with_prism_test_points_normal_sidewall; - intersect_line_with_prism_test_points_normal_sidewall.num_items = 3; + intersect_line_with_prism_test_points_normal_sidewall.num_items = 9; intersect_line_with_prism_test_points_normal_sidewall.items = (vector3 *)malloc(intersect_line_with_prism_test_points_normal_sidewall.num_items * sizeof(vector3)); intersect_line_with_prism_test_points_normal_sidewall.items[0] = make_vector3(100.809, 144.033, 130.205); // line crossing top[15] to bottom[11] intersect_line_with_prism_test_points_normal_sidewall.items[1] = make_vector3(17.0383, 123.450, 63.5000); // line crossing midpoint 13-14 face to midpoint 9-10 face intersect_line_with_prism_test_points_normal_sidewall.items[2] = make_vector3(17.0383, 123.450, 63.5000); // line crossing midpoint 13-14 face to midpoint 9-10 face + intersect_line_with_prism_test_points_normal_sidewall.items[3] = make_vector3(17.0383, 123.450, 63.5000); // line crossing midpoint 13-14 face to midpoint 9-10 face + intersect_line_with_prism_test_points_normal_sidewall.items[4] = make_vector3(12.7914, 70.2440, 63.5000); // interior point between 4, 5, 12, 13 in positive xhat + intersect_line_with_prism_test_points_normal_sidewall.items[5] = make_vector3(12.7914, 70.2440, 63.5000); // interior point between 4, 5, 12, 13 in negative xhat + intersect_line_with_prism_test_points_normal_sidewall.items[6] = make_vector3(40.1648, 142.861, 131.290); // between top point 14 and center of c on bottom + intersect_line_with_prism_test_points_normal_sidewall.items[7] = make_vector3(41.1477, 0.00000, 127.000); // between top point 11 and origin + intersect_line_with_prism_test_points_normal_sidewall.items[8] = make_vector3(51.7447, 114.905, 127.000); // between top point 3 and center of c on bottom vector3 intersect_line_with_prism_test_vectors_normal_sidewall[intersect_line_with_prism_test_points_normal_sidewall.num_items]; intersect_line_with_prism_test_vectors_normal_sidewall[0] = make_vector3(-0.29372, -0.709099, -0.64102); // line crossing top[15] to bottom[11] intersect_line_with_prism_test_vectors_normal_sidewall[1] = make_vector3(0.707107, -0.707107, 0.000000); // line crossing midpoint 13-14 face to midpoint 9-10 face intersect_line_with_prism_test_vectors_normal_sidewall[2] = make_vector3(0.707107, -0.707107, 0.000000); // line crossing midpoint 13-14 face to midpoint 9-10 face + intersect_line_with_prism_test_vectors_normal_sidewall[3] = make_vector3(0.707107, -0.707107, 0.000000); // line crossing midpoint 13-14 face to midpoint 9-10 face + intersect_line_with_prism_test_vectors_normal_sidewall[4] = make_vector3(1.000000, 0.0000000, 0.000000); // interior point between 4, 5, 12, 13 in positive xhat + intersect_line_with_prism_test_vectors_normal_sidewall[5] = make_vector3(-1.00000, 0.0000000, 0.000000); // interior point between 4, 5, 12, 13 in negative xhat + intersect_line_with_prism_test_vectors_normal_sidewall[6] = make_vector3(0.196571, -0.474559,-0.857994); // between top point 14 and center of c on bottom + intersect_line_with_prism_test_vectors_normal_sidewall[7] = make_vector3(-0.308223, 0.000000,-0.951314); // between top point 11 and origin + intersect_line_with_prism_test_vectors_normal_sidewall[8] = make_vector3(0.136135, -0.328658,-0.934586); // between top point 3 and center of c on bottom + + double intersect_line_with_prism_expected_normal_sidewall[intersect_line_with_prism_test_points_normal_sidewall.num_items]; + intersect_line_with_prism_expected_normal_sidewall[0] = 36.07816398; // line crossing top[15] to bottom[11] + intersect_line_with_prism_expected_normal_sidewall[1] = 25.58291121; // line crossing midpoint 13-14 face to midpoint 9-10 face + intersect_line_with_prism_expected_normal_sidewall[2] = 25.58291120; // line crossing midpoint 13-14 face to midpoint 9-10 face + intersect_line_with_prism_expected_normal_sidewall[3] = 51.16582241; // line crossing midpoint 13-14 face to midpoint 9-10 face + intersect_line_with_prism_expected_normal_sidewall[4] = 12.79135000; // interior point between 4, 5, 12, 13 in positive xhat + intersect_line_with_prism_expected_normal_sidewall[5] = 12.79135000; // interior point between 4, 5, 12, 13 in negative xhat + intersect_line_with_prism_expected_normal_sidewall[6] = 53.90914485; // between top point 14 and center of c on bottom + intersect_line_with_prism_expected_normal_sidewall[7] = 0.000000000; // between top point 11 and origin + intersect_line_with_prism_expected_normal_sidewall[8] = 0.000000000; // between top point 3 and center of c on bottom double intersect_line_with_prism_a_normal_sidewall[intersect_line_with_prism_test_points_normal_sidewall.num_items]; intersect_line_with_prism_a_normal_sidewall[0] = 0; // line crossing top[15] to bottom[11] intersect_line_with_prism_a_normal_sidewall[1] = 0; // line crossing midpoint 13-14 face to midpoint 9-10 face intersect_line_with_prism_a_normal_sidewall[2] = 100; // line crossing midpoint 13-14 face to midpoint 9-10 face + intersect_line_with_prism_a_normal_sidewall[3] = 0; // line crossing midpoint 13-14 face to midpoint 9-10 face + intersect_line_with_prism_a_normal_sidewall[4] = 0; // interior point between 4, 5, 12, 13 in positive xhat + intersect_line_with_prism_a_normal_sidewall[5] = 0; // interior point between 4, 5, 12, 13 in negative xhat + intersect_line_with_prism_a_normal_sidewall[6] = 0; // between top point 14 and center of c on bottom + intersect_line_with_prism_a_normal_sidewall[7] = 0; // between top point 11 and origin + intersect_line_with_prism_a_normal_sidewall[8] = 0; // between top point 3 and center of c on bottom double intersect_line_with_prism_b_normal_sidewall[intersect_line_with_prism_test_points_normal_sidewall.num_items]; intersect_line_with_prism_b_normal_sidewall[0] = 150; // line crossing top[15] to bottom[11] intersect_line_with_prism_b_normal_sidewall[1] = 100; // line crossing midpoint 13-14 face to midpoint 9-10 face intersect_line_with_prism_b_normal_sidewall[2] = 150; // line crossing midpoint 13-14 face to midpoint 9-10 face - - double intersect_line_with_prism_expected_normal_sidewall[intersect_line_with_prism_test_points_normal_sidewall.num_items]; - intersect_line_with_prism_expected_normal_sidewall[0] = 36.07816398; // line crossing top[15] to bottom[11] - intersect_line_with_prism_expected_normal_sidewall[1] = 25.58291121; // line crossing midpoint 13-14 face to midpoint 9-10 face - intersect_line_with_prism_expected_normal_sidewall[2] = 25.58291120; // line crossing midpoint 13-14 face to midpoint 9-10 face + intersect_line_with_prism_b_normal_sidewall[3] = 150; // line crossing midpoint 13-14 face to midpoint 9-10 face + intersect_line_with_prism_b_normal_sidewall[4] = 300; // interior point between 4, 5, 12, 13 in positive xhat + intersect_line_with_prism_b_normal_sidewall[5] = 300; // interior point between 4, 5, 12, 13 in negative xhat + intersect_line_with_prism_b_normal_sidewall[6] = 300; // between top point 14 and center of c on bottom + intersect_line_with_prism_b_normal_sidewall[7] = 300; // between top point 11 and origin + intersect_line_with_prism_b_normal_sidewall[8] = 300; // between top point 3 and center of c on bottom double intersect_line_with_prism_actual_normal_sidewall[intersect_line_with_prism_test_points_normal_sidewall.num_items]; for (int i = 0; i < intersect_line_with_prism_test_points_normal_sidewall.num_items; i++) { @@ -965,21 +995,61 @@ int test_helper_functions_on_octagonal_c_prism() { } vector3_list intersect_line_with_prism_test_points_tapered_sidewall; - intersect_line_with_prism_test_points_tapered_sidewall.num_items = 1; + intersect_line_with_prism_test_points_tapered_sidewall.num_items = 9; intersect_line_with_prism_test_points_tapered_sidewall.items = (vector3 *)malloc(intersect_line_with_prism_test_points_tapered_sidewall.num_items * sizeof(vector3)); intersect_line_with_prism_test_points_tapered_sidewall.items[0] = make_vector3(98.4872, 138.429, 130.281); // line crossing top[15] to bottom[11] + intersect_line_with_prism_test_points_tapered_sidewall.items[1] = make_vector3(19.0383, 121.528, 63.5000); // line crossing midpoint 13-14 face to midpoint 9-10 face + intersect_line_with_prism_test_points_tapered_sidewall.items[2] = make_vector3(19.0383, 121.528, 63.5000); // line crossing midpoint 13-14 face to midpoint 9-10 face + intersect_line_with_prism_test_points_tapered_sidewall.items[3] = make_vector3(19.0383, 121.528, 63.5000); // line crossing midpoint 13-14 face to midpoint 9-10 face + intersect_line_with_prism_test_points_tapered_sidewall.items[4] = make_vector3(12.7914, 70.2440, 63.5000); // interior point between 4, 5, 12, 13 in positive xhat + intersect_line_with_prism_test_points_tapered_sidewall.items[5] = make_vector3(12.7914, 70.2440, 63.5000); // interior point between 4, 5, 12, 13 in negative xhat + intersect_line_with_prism_test_points_tapered_sidewall.items[6] = make_vector3(43.4445, 134.943, 127.000); // between top point 14 and center of c on bottom + intersect_line_with_prism_test_points_tapered_sidewall.items[7] = make_vector3(43.4445, 5.54494, 127.000); // between top point 11 and origin + intersect_line_with_prism_test_points_tapered_sidewall.items[8] = make_vector3(34.7428, 105.745, 127.000); // between top point 3 and center of c on bottom vector3 intersect_line_with_prism_test_vectors_tapered_sidewall[intersect_line_with_prism_test_points_tapered_sidewall.num_items]; intersect_line_with_prism_test_vectors_tapered_sidewall[0] = make_vector3(-0.288786, -0.697187, -0.656149); // line crossing top[15] to bottom[11] + intersect_line_with_prism_test_vectors_tapered_sidewall[1] = make_vector3(0.6992010, -0.714925, 0.0000000); // line crossing midpoint 13-14 face to midpoint 9-10 face + intersect_line_with_prism_test_vectors_tapered_sidewall[2] = make_vector3(0.6992010, -0.714925, 0.0000000); // line crossing midpoint 13-14 face to midpoint 9-10 face + intersect_line_with_prism_test_vectors_tapered_sidewall[3] = make_vector3(0.6992010, -0.714925, 0.0000000); // line crossing midpoint 13-14 face to midpoint 9-10 face + intersect_line_with_prism_test_vectors_tapered_sidewall[4] = make_vector3(1.0000000, 0.0000000, 0.0000000); // interior point between 4, 5, 12, 13 in positive xhat + intersect_line_with_prism_test_vectors_tapered_sidewall[5] = make_vector3(-1.000000, 0.0000000, 0.0000000); // interior point between 4, 5, 12, 13 in negative xhat + intersect_line_with_prism_test_vectors_tapered_sidewall[6] = make_vector3(0.1847880,-0.4461140, -0.875692); // between top point 14 and center of c on bottom + intersect_line_with_prism_test_vectors_tapered_sidewall[7] = make_vector3(-0.323393,-0.0412755, -0.945364); // between top point 11 and origin + intersect_line_with_prism_test_vectors_tapered_sidewall[8] = make_vector3(0.2599600,-0.2599600, -0.929969); // between top point 3 and center of c on bottom double intersect_line_with_prism_expected_tapered_sidewall[intersect_line_with_prism_test_points_tapered_sidewall.num_items]; intersect_line_with_prism_expected_tapered_sidewall[0] = 21.67860775; // line crossing top[15] to bottom[11] + intersect_line_with_prism_expected_tapered_sidewall[1] = 20.03920840; // line crossing midpoint 13-14 face to midpoint 9-10 face + intersect_line_with_prism_expected_tapered_sidewall[2] = 20.03919670; // line crossing midpoint 13-14 face to midpoint 9-10 face + intersect_line_with_prism_expected_tapered_sidewall[3] = 40.07840510; // line crossing midpoint 13-14 face to midpoint 9-10 face + intersect_line_with_prism_expected_tapered_sidewall[4] = 10.01888013; // interior point between 4, 5, 12, 13 in positive xhat + intersect_line_with_prism_expected_tapered_sidewall[5] = 10.01888013; // interior point between 4, 5, 12, 13 in negative xhat + intersect_line_with_prism_expected_tapered_sidewall[6] = 35.53300107; // between top point 14 and center of c on bottom + intersect_line_with_prism_expected_tapered_sidewall[7] = 0.000000000; // between top point 11 and origin + intersect_line_with_prism_expected_tapered_sidewall[8] = 0.000000000; // between top point 3 and center of c on bottom double intersect_line_with_prism_a_tapered_sidewall[intersect_line_with_prism_test_points_tapered_sidewall.num_items]; - intersect_line_with_prism_a_tapered_sidewall[0] = 0; // line crossing top[15] to bottom[11] + intersect_line_with_prism_a_tapered_sidewall[0] = 0; // line crossing top[15] to bottom[11] + intersect_line_with_prism_a_tapered_sidewall[1] = 0; // line crossing midpoint 13-14 face to midpoint 9-10 face + intersect_line_with_prism_a_tapered_sidewall[2] = 50; // line crossing midpoint 13-14 face to midpoint 9-10 face + intersect_line_with_prism_a_tapered_sidewall[3] = 0; // line crossing midpoint 13-14 face to midpoint 9-10 face + intersect_line_with_prism_a_tapered_sidewall[4] = 0; // interior point between 4, 5, 12, 13 in positive xhat + intersect_line_with_prism_a_tapered_sidewall[5] = 0; // interior point between 4, 5, 12, 13 in negative xhat + intersect_line_with_prism_a_tapered_sidewall[6] = 0; // between top point 14 and center of c on bottom + intersect_line_with_prism_a_tapered_sidewall[7] = 0; // between top point 11 and origin + intersect_line_with_prism_a_tapered_sidewall[8] = 0; // between top point 3 and center of c on bottom double intersect_line_with_prism_b_tapered_sidewall[intersect_line_with_prism_test_points_tapered_sidewall.num_items]; intersect_line_with_prism_b_tapered_sidewall[0] = 150; // line crossing top[15] to bottom[11] + intersect_line_with_prism_b_tapered_sidewall[1] = 50; // line crossing midpoint 13-14 face to midpoint 9-10 face + intersect_line_with_prism_b_tapered_sidewall[2] = 150; // line crossing midpoint 13-14 face to midpoint 9-10 face + intersect_line_with_prism_b_tapered_sidewall[3] = 150; // line crossing midpoint 13-14 face to midpoint 9-10 face + intersect_line_with_prism_b_tapered_sidewall[4] = 300; // interior point between 4, 5, 12, 13 in positive xhat + intersect_line_with_prism_b_tapered_sidewall[5] = 300; // interior point between 4, 5, 12, 13 in negative xhat + intersect_line_with_prism_b_tapered_sidewall[6] = 300; // between top point 14 and center of c on bottom + intersect_line_with_prism_b_tapered_sidewall[7] = 300; // between top point 11 and origin + intersect_line_with_prism_b_tapered_sidewall[8] = 300; // between top point 3 and center of c on bottom double intersect_line_with_prism_actual_tapered_sidewall[intersect_line_with_prism_test_points_tapered_sidewall.num_items]; for (int i = 0; i < intersect_line_with_prism_test_points_tapered_sidewall.num_items; i++) { @@ -1009,7 +1079,7 @@ int test_helper_functions_on_octagonal_c_prism() { } } - printf("\n\tprism helper function testing summary: \n\t\t%i/%i tests failed with normal sidewall\n\t\t%i/%i tests failed with tapered sidewall\n", num_failed_normal, num_tests_normal, num_failed_tapered, num_tests_tapered); + printf("\tprism helper function testing summary: \n\t\t%i/%i tests failed with normal sidewall\n\t\t%i/%i tests failed with tapered sidewall\n", num_failed_normal, num_tests_normal, num_failed_tapered, num_tests_tapered); return num_failed_normal + num_failed_tapered; } From 3d5d42e78522d9a2131e00695a6fc9847cf166d6 Mon Sep 17 00:00:00 2001 From: danielwboyce Date: Sun, 9 Feb 2020 18:46:11 -0700 Subject: [PATCH 57/63] Change to init_prism so that it is no longer O(n^2) --- utils/geom.c | 62 +++++++++++++++++++++++++++++++--------------------- 1 file changed, 37 insertions(+), 25 deletions(-) diff --git a/utils/geom.c b/utils/geom.c index f6aa7b5..2d8b4ab 100644 --- a/utils/geom.c +++ b/utils/geom.c @@ -2718,6 +2718,39 @@ void init_prism(geometric_object *o) { vector3 a1, a2, v; // v will be defined as a2 - a1 } edge; + // find the point at the bottom left corner of the polygon + double smallest_x = HUGE_VAL; + double smallest_y = HUGE_VAL; + int index_for_point_a = -1; + int index_for_point_b = -1; + int index_for_point_c = -1; + for (nv = 0; nv < num_vertices; nv++) { + double current_x = prsm->vertices_bottom_p.items[nv].x; + double current_y = prsm->vertices_bottom_p.items[nv].y; + if (current_x < smallest_x) { + smallest_x = current_x; + smallest_y = current_y; + index_for_point_b = nv; + } + else if (current_x == smallest_x && current_y < smallest_y) { + smallest_y = current_y; + index_for_point_b = nv; + } + } + if (index_for_point_b == -1) { + exit(EXIT_FAILURE); + } + else { + index_for_point_a = (index_for_point_b + 1 == num_vertices ? 0 : index_for_point_b + 1); + index_for_point_c = (index_for_point_b - 1 == -1 ? num_vertices - 1 : index_for_point_b - 1); + } + // find orientation of the polygon + vector3 A = prsm->vertices_bottom_p.items[index_for_point_a]; + vector3 B = prsm->vertices_bottom_p.items[index_for_point_b]; + vector3 C = prsm->vertices_bottom_p.items[index_for_point_c]; + double orientation_number = (B.x - A.x)*(C.y - A.y)-(C.x - A.x)*(B.y - A.y); + int orientation_positive_or_negative = (orientation_number < 0 ? 0 : 1); + edge *top_polygon_edges; top_polygon_edges = (edge *)malloc(num_vertices * sizeof(edge)); number w = prsm->height / tan(theta); @@ -2727,39 +2760,18 @@ void init_prism(geometric_object *o) { top_polygon_edges[nv].a2 = prsm->vertices_top_p.items[nv]; top_polygon_edges[nv].v = vector3_minus(top_polygon_edges[nv].a2, top_polygon_edges[nv].a1); - vector3 normal_vector; - normal_vector.x = top_polygon_edges[nv].v.y; - normal_vector.y = -1 * top_polygon_edges[nv].v.x; - normal_vector.z = 0; - normal_vector = unit_vector3(normal_vector); + vector3 normal_vector = (orientation_positive_or_negative ? unit_vector3(vector3_cross(top_polygon_edges[nv].v, zhat)) : unit_vector3(vector3_cross(top_polygon_edges[nv].v, vector3_scale(-1, zhat)))); vector3 offset = vector3_scale(w, normal_vector); - vector3 midpoint = vector3_plus(top_polygon_edges[nv].a1, vector3_scale(0.5, top_polygon_edges[nv].v)); - boolean midpoint_on_side_of_postive_offset_is_in_polygon = node_in_or_on_polygon(vector3_plus(midpoint, vector3_scale(1e-3, offset)), prsm->vertices_top_p.items, prsm->vertices_top_p.num_items, 1); - - if (midpoint_on_side_of_postive_offset_is_in_polygon) { - // positive sidewall angles means the prism tapers in towards to the rest of the prism body - if (prsm->sidewall_angle > 0) { + // positive sidewall angles means the prism tapers in towards the rest of the prism body + if (prsm->sidewall_angle > 0) { top_polygon_edges[nv].a1 = vector3_plus(top_polygon_edges[nv].a1, offset); top_polygon_edges[nv].a2 = vector3_plus(top_polygon_edges[nv].a2, offset); - } - // negative sidewall angles means the prism tapers out away from the rest of the prism body - else { - top_polygon_edges[nv].a1 = vector3_minus(top_polygon_edges[nv].a1, offset); - top_polygon_edges[nv].a2 = vector3_minus(top_polygon_edges[nv].a2, offset); - } } + // negative sidewall angles means the prism tapers out away from the rest of the prism body else { - // positive sidewall angles means the prism tapers in towards to the rest of the prism body - if (prsm->sidewall_angle > 0) { top_polygon_edges[nv].a1 = vector3_minus(top_polygon_edges[nv].a1, offset); top_polygon_edges[nv].a2 = vector3_minus(top_polygon_edges[nv].a2, offset); - } - // negative sidewall angles means the prism tapers out away from the rest of the prism body - else { - top_polygon_edges[nv].a1 = vector3_plus(top_polygon_edges[nv].a1, offset); - top_polygon_edges[nv].a2 = vector3_plus(top_polygon_edges[nv].a2, offset); - } } } From 74664f65ae5aaaaac5009e98dba5443b6e09217e Mon Sep 17 00:00:00 2001 From: danielwboyce Date: Sun, 9 Feb 2020 19:05:36 -0700 Subject: [PATCH 58/63] Add Daniel as a contributor --- AUTHORS | 1 + 1 file changed, 1 insertion(+) diff --git a/AUTHORS b/AUTHORS index 996550d..6f57dbb 100644 --- a/AUTHORS +++ b/AUTHORS @@ -3,6 +3,7 @@ libctl was written by Steven G. Johnson (stevenj@alum.mit.edu) with contribution M.T. Homer Reid Christopher Hogan Ardavan Oskooi +Daniel W. Boyce The multidimensional integration routines in src/integrator.c were adapted from the HIntlib Library by Rudolf Schuerer and from the GNU Scientific From ec44c2ca735369e73670f1d903dbb81173d0fbde Mon Sep 17 00:00:00 2001 From: danielwboyce Date: Mon, 10 Feb 2020 08:42:10 -0700 Subject: [PATCH 59/63] Remove isnan check --- utils/geom.c | 3 --- 1 file changed, 3 deletions(-) diff --git a/utils/geom.c b/utils/geom.c index 2d8b4ab..38d37ae 100644 --- a/utils/geom.c +++ b/utils/geom.c @@ -2701,9 +2701,6 @@ void init_prism(geometric_object *o) { // * A linearly interpolated value of the polygon vertices between the bottom // polygon and the top can be found // vertices_bottom_p + top_polygon_diff_vectors_scaled_p * z - if (isnan(prsm->sidewall_angle)) { - prsm->sidewall_angle = 0.0; - } number theta = (K_PI/2) - fabs(prsm->sidewall_angle); prsm->vertices_top_p.num_items = num_vertices; prsm->vertices_top_p.items = (vector3 *)malloc(num_vertices * sizeof(vector3)); From 629f02d9ae512b343834922517237e748c098cfc Mon Sep 17 00:00:00 2001 From: danielwboyce Date: Mon, 10 Feb 2020 08:49:47 -0700 Subject: [PATCH 60/63] Change offset definition to be simpler --- utils/geom.c | 12 +++--------- 1 file changed, 3 insertions(+), 9 deletions(-) diff --git a/utils/geom.c b/utils/geom.c index 38d37ae..e96e884 100644 --- a/utils/geom.c +++ b/utils/geom.c @@ -2758,18 +2758,12 @@ void init_prism(geometric_object *o) { top_polygon_edges[nv].v = vector3_minus(top_polygon_edges[nv].a2, top_polygon_edges[nv].a1); vector3 normal_vector = (orientation_positive_or_negative ? unit_vector3(vector3_cross(top_polygon_edges[nv].v, zhat)) : unit_vector3(vector3_cross(top_polygon_edges[nv].v, vector3_scale(-1, zhat)))); - vector3 offset = vector3_scale(w, normal_vector); // positive sidewall angles means the prism tapers in towards the rest of the prism body - if (prsm->sidewall_angle > 0) { - top_polygon_edges[nv].a1 = vector3_plus(top_polygon_edges[nv].a1, offset); - top_polygon_edges[nv].a2 = vector3_plus(top_polygon_edges[nv].a2, offset); - } // negative sidewall angles means the prism tapers out away from the rest of the prism body - else { - top_polygon_edges[nv].a1 = vector3_minus(top_polygon_edges[nv].a1, offset); - top_polygon_edges[nv].a2 = vector3_minus(top_polygon_edges[nv].a2, offset); - } + vector3 offset = vector3_scale(prsm->sidewall_angle > 0 ? w : -w, normal_vector); + top_polygon_edges[nv].a1 = vector3_plus(top_polygon_edges[nv].a1, offset); + top_polygon_edges[nv].a2 = vector3_plus(top_polygon_edges[nv].a2, offset); } for (nv = 0; nv < num_vertices; nv++) { From 30ed67959665d49074b0a0fa104b5c713f4196a6 Mon Sep 17 00:00:00 2001 From: danielwboyce Date: Mon, 10 Feb 2020 10:08:17 -0700 Subject: [PATCH 61/63] Addition of make_slanted_prism_with_center to maintain ABI compatibility --- utils/ctlgeom.h | 8 +++++++- utils/geom.c | 19 +++++++++++++------ 2 files changed, 20 insertions(+), 7 deletions(-) diff --git a/utils/ctlgeom.h b/utils/ctlgeom.h index 6e87915..a21fd5c 100644 --- a/utils/ctlgeom.h +++ b/utils/ctlgeom.h @@ -159,8 +159,14 @@ extern boolean node_in_or_on_polygon(vector3 q0, vector3 *nodes, int num_nodes, GEOMETRIC_OBJECT make_prism(MATERIAL_TYPE material, const vector3 *vertices_bottom, int num_vertices, double height, vector3 axis, double sidewall_angle); -// as make_prism, but with a rigid translation so that the prism is centered at center +// Same as make_prism, but with a rigid translation so that the prism is centered at center. Have both +// make_prism_with_center and make_slanted_prism_with_center to maintain ABI compatibility, though +// make_prism_with_center just calls make_slanted_prism_with_center with the sidewall angle equal to zero. GEOMETRIC_OBJECT make_prism_with_center(MATERIAL_TYPE material, vector3 center, + const vector3 *vertices_bottom, int num_vertices, double height, + vector3 axis; + +GEOMETRIC_OBJECT make_slanted_prism_with_center(MATERIAL_TYPE material, vector3 center, const vector3 *vertices_bottom, int num_vertices, double height, vector3 axis, double sidewall_angle); diff --git a/utils/geom.c b/utils/geom.c index e96e884..2cb908b 100644 --- a/utils/geom.c +++ b/utils/geom.c @@ -2818,14 +2818,16 @@ void init_prism(geometric_object *o) { // height, axis, and sidewall_angle geometric_object make_prism(material_type material, const vector3 *vertices_bottom, int num_vertices, double height, vector3 axis, double sidewall_angle) { - return make_prism_with_center(material, auto_center, vertices_bottom, num_vertices, height, axis, - sidewall_angle); + if (sidewall_angle == 0) return make_prism_with_center(material, auto_center, vertices_bottom, num_vertices, height, axis); + else return make_slanted_prism_with_center(material, center, vertices_bottom, num_vertices, height, axis, sidewall_angle); } -// prism in which all vertices are translated to ensure that the prism is centered at center -geometric_object make_prism_with_center(material_type material, vector3 center, - const vector3 *vertices_bottom, int num_vertices, double height, - vector3 axis, double sidewall_angle) { +// prism in which all vertices are translated to ensure that the prism is centered at center. Have both +// make_prism_with_center and make_slanted_prism_with_center to maintain ABI compatibility, though +// make_prism_with_center just calls make_slanted_prism_with_center with the sidewall angle equal to zero. +geometric_object make_slanted_prism_with_center(material_type material, vector3 center, + const vector3 *vertices_bottom, int num_vertices, double height, + vector3 axis, double sidewall_angle) { geometric_object o = make_geometric_object(material, center); o.which_subclass = GEOM PRISM; prism *prsm = o.subclass.prism_data = MALLOC1(prism); @@ -2840,3 +2842,8 @@ geometric_object make_prism_with_center(material_type material, vector3 center, init_prism(&o); return o; } + +geometric_object make_prism_with_center(material_type material, vector3 center, const vector3 *vertices_bottom, + int num_vertices, double height, vector3 axis) { + return make_slanted_prism_with_center(material, center, vertices_bottom, num_vertices, height, axis, 0) +} From 2df36730d1c7fc1499a17f6be9bd7de7a64c5411 Mon Sep 17 00:00:00 2001 From: danielwboyce Date: Mon, 10 Feb 2020 11:10:08 -0700 Subject: [PATCH 62/63] Fixed some typos --- utils/ctlgeom.h | 2 +- utils/geom.c | 4 ++-- 2 files changed, 3 insertions(+), 3 deletions(-) diff --git a/utils/ctlgeom.h b/utils/ctlgeom.h index a21fd5c..1b289fe 100644 --- a/utils/ctlgeom.h +++ b/utils/ctlgeom.h @@ -164,7 +164,7 @@ GEOMETRIC_OBJECT make_prism(MATERIAL_TYPE material, const vector3 *vertices_bott // make_prism_with_center just calls make_slanted_prism_with_center with the sidewall angle equal to zero. GEOMETRIC_OBJECT make_prism_with_center(MATERIAL_TYPE material, vector3 center, const vector3 *vertices_bottom, int num_vertices, double height, - vector3 axis; + vector3 axis); GEOMETRIC_OBJECT make_slanted_prism_with_center(MATERIAL_TYPE material, vector3 center, const vector3 *vertices_bottom, int num_vertices, double height, diff --git a/utils/geom.c b/utils/geom.c index 2cb908b..a056e6a 100644 --- a/utils/geom.c +++ b/utils/geom.c @@ -2819,7 +2819,7 @@ void init_prism(geometric_object *o) { geometric_object make_prism(material_type material, const vector3 *vertices_bottom, int num_vertices, double height, vector3 axis, double sidewall_angle) { if (sidewall_angle == 0) return make_prism_with_center(material, auto_center, vertices_bottom, num_vertices, height, axis); - else return make_slanted_prism_with_center(material, center, vertices_bottom, num_vertices, height, axis, sidewall_angle); + else return make_slanted_prism_with_center(material, auto_center, vertices_bottom, num_vertices, height, axis, sidewall_angle); } // prism in which all vertices are translated to ensure that the prism is centered at center. Have both @@ -2845,5 +2845,5 @@ geometric_object make_slanted_prism_with_center(material_type material, vector3 geometric_object make_prism_with_center(material_type material, vector3 center, const vector3 *vertices_bottom, int num_vertices, double height, vector3 axis) { - return make_slanted_prism_with_center(material, center, vertices_bottom, num_vertices, height, axis, 0) + return make_slanted_prism_with_center(material, center, vertices_bottom, num_vertices, height, axis, 0); } From af95319c4c55834012f9b103b9eff9e399140553 Mon Sep 17 00:00:00 2001 From: danielwboyce Date: Tue, 11 Feb 2020 12:30:31 -0700 Subject: [PATCH 63/63] Didn't maintain ABI compatibility, should be now. User uses make_slanted_prism to make a prism with a nonzero sidewall angle and make_prism for a prism with a normal sidewall --- utils/ctlgeom.h | 17 ++++++++++------- utils/geom.c | 42 +++++++++++++++++++++++------------------- utils/test-prism.c | 16 ++++++++-------- 3 files changed, 41 insertions(+), 34 deletions(-) diff --git a/utils/ctlgeom.h b/utils/ctlgeom.h index 1b289fe..0bf19ee 100644 --- a/utils/ctlgeom.h +++ b/utils/ctlgeom.h @@ -155,17 +155,20 @@ GEOMETRIC_OBJECT make_ellipsoid(MATERIAL_TYPE material, vector3 center, vector3 extern boolean node_in_or_on_polygon(vector3 q0, vector3 *nodes, int num_nodes, boolean include_boundaries); -// prism with `center` field computed automatically from bottom vertices, height, axis, sidewall angle -GEOMETRIC_OBJECT make_prism(MATERIAL_TYPE material, const vector3 *vertices_bottom, int num_vertices, - double height, vector3 axis, double sidewall_angle); +// prism with `center` field computed automatically from vertices, height, axis +GEOMETRIC_OBJECT make_prism(MATERIAL_TYPE material, const vector3 *vertices, int num_vertices, + double height, vector3 axis); -// Same as make_prism, but with a rigid translation so that the prism is centered at center. Have both -// make_prism_with_center and make_slanted_prism_with_center to maintain ABI compatibility, though -// make_prism_with_center just calls make_slanted_prism_with_center with the sidewall angle equal to zero. +// as make_prism, but with a rigid translation so that the prism is centered at center GEOMETRIC_OBJECT make_prism_with_center(MATERIAL_TYPE material, vector3 center, - const vector3 *vertices_bottom, int num_vertices, double height, + const vector3 *vertices, int num_vertices, double height, vector3 axis); +// slanted prism with `center` field computed automatically from vertices, height, axis, sidewall_angle +GEOMETRIC_OBJECT make_slanted_prism(MATERIAL_TYPE material, const vector3 *vertices_bottom, int num_vertices, + double height, vector3 axis, double sidewall_angle); + +// as make_slanted_prism, but with a rigid translation so that the prism is centered at center GEOMETRIC_OBJECT make_slanted_prism_with_center(MATERIAL_TYPE material, vector3 center, const vector3 *vertices_bottom, int num_vertices, double height, vector3 axis, double sidewall_angle); diff --git a/utils/geom.c b/utils/geom.c index a056e6a..544039d 100644 --- a/utils/geom.c +++ b/utils/geom.c @@ -2814,20 +2814,29 @@ void init_prism(geometric_object *o) { /***************************************************************/ /* routines called from C++ or python codes to create prisms */ /***************************************************************/ -// prism with center determined automatically from vertices_bottom, -// height, axis, and sidewall_angle -geometric_object make_prism(material_type material, const vector3 *vertices_bottom, int num_vertices, - double height, vector3 axis, double sidewall_angle) { - if (sidewall_angle == 0) return make_prism_with_center(material, auto_center, vertices_bottom, num_vertices, height, axis); - else return make_slanted_prism_with_center(material, auto_center, vertices_bottom, num_vertices, height, axis, sidewall_angle); -} - -// prism in which all vertices are translated to ensure that the prism is centered at center. Have both -// make_prism_with_center and make_slanted_prism_with_center to maintain ABI compatibility, though -// make_prism_with_center just calls make_slanted_prism_with_center with the sidewall angle equal to zero. -geometric_object make_slanted_prism_with_center(material_type material, vector3 center, - const vector3 *vertices_bottom, int num_vertices, double height, - vector3 axis, double sidewall_angle) { +// prism with center determined automatically from vertices, height, and axis +geometric_object make_prism(material_type material, const vector3 *vertices, int num_vertices, + double height, vector3 axis) { + return make_prism_with_center(material, auto_center, vertices, num_vertices, height, axis); +} + +// prism in which all vertices are translated to ensure that the prism is centered at center. +geometric_object make_prism_with_center(material_type material, vector3 center, const vector3 *vertices_bottom, + int num_vertices, double height, vector3 axis) { + return make_slanted_prism_with_center(material, center, vertices_bottom, num_vertices, height, axis, 0); +} + +// slanted prism with center determined automatically from vertices, height, axis, and sidewall_angle +geometric_object make_slanted_prism(material_type material, const vector3 *vertices_bottom, + int num_vertices, double height, vector3 axis, double sidewall_angle) { + return make_slanted_prism_with_center(material, auto_center, vertices_bottom, num_vertices, height, axis, sidewall_angle); +} + +// Have both make_prism_with_center and make_slanted_prism_with_center keep the same parameters to maintain ABI +// compatibility, though make_prism_with_center just calls make_slanted_prism_with_center with the sidewall angle equal +// to zero. To make a slanted prism, the user will have to call make_slanted_prism for now. +geometric_object make_slanted_prism_with_center(material_type material, vector3 center, const vector3 *vertices_bottom, + int num_vertices, double height, vector3 axis, double sidewall_angle) { geometric_object o = make_geometric_object(material, center); o.which_subclass = GEOM PRISM; prism *prsm = o.subclass.prism_data = MALLOC1(prism); @@ -2842,8 +2851,3 @@ geometric_object make_slanted_prism_with_center(material_type material, vector3 init_prism(&o); return o; } - -geometric_object make_prism_with_center(material_type material, vector3 center, const vector3 *vertices_bottom, - int num_vertices, double height, vector3 axis) { - return make_slanted_prism_with_center(material, center, vertices_bottom, num_vertices, height, axis, 0); -} diff --git a/utils/test-prism.c b/utils/test-prism.c index f192ad6..56c8b53 100644 --- a/utils/test-prism.c +++ b/utils/test-prism.c @@ -479,11 +479,11 @@ int test_square_base_sidewall_prisms_to_gnuplot() { vector3 zhat = make_vector3(0, 0, 1); double normal_sidewall = 0; - geometric_object square_normal_sidewall_geom_object = make_prism(m, nodes_square, num_nodes_square, height_square, zhat, normal_sidewall); + geometric_object square_normal_sidewall_geom_object = make_prism(m, nodes_square, num_nodes_square, height_square, zhat); prism *square_normal_sidewall_prism = square_normal_sidewall_geom_object.subclass.prism_data; double one_degree_sidewall = 1.0 * 2 * K_PI / 360.0; - geometric_object square_one_degree_sidewall_geom_object = make_prism(m, nodes_square, num_nodes_square, height_square, zhat, one_degree_sidewall); + geometric_object square_one_degree_sidewall_geom_object = make_slanted_prism(m, nodes_square, num_nodes_square, height_square, zhat, one_degree_sidewall); prism *square_one_degree_sidewall_prism = square_one_degree_sidewall_geom_object.subclass.prism_data; prism2gnuplot(square_normal_sidewall_prism, "square_normal_sidewall_gnu_plot.dat"); @@ -523,11 +523,11 @@ int test_octagon_c_base_sidewall_prisms_to_gnuplot() { vector3 zhat = make_vector3(0, 0, 1); double normal_sidewall = 0; - geometric_object octagon_c_normal_sidewall_geom_object = make_prism(m, nodes_octagon_c, num_nodes_octagon_c, height_octagon_c, zhat, normal_sidewall); + geometric_object octagon_c_normal_sidewall_geom_object = make_prism(m, nodes_octagon_c, num_nodes_octagon_c, height_octagon_c, zhat); prism *octagon_c_normal_sidewall_prism = octagon_c_normal_sidewall_geom_object.subclass.prism_data; double two_half_degree_sidewall = 2.5 * 2 * K_PI / 360.0; - geometric_object octagon_c_two_half_degree_sidewall_geom_object = make_prism(m, nodes_octagon_c, num_nodes_octagon_c, height_octagon_c, zhat, two_half_degree_sidewall); + geometric_object octagon_c_two_half_degree_sidewall_geom_object = make_slanted_prism(m, nodes_octagon_c, num_nodes_octagon_c, height_octagon_c, zhat, two_half_degree_sidewall); prism *octagon_c_two_half_degree_sidewall_prism = octagon_c_two_half_degree_sidewall_geom_object.subclass.prism_data; prism2gnuplot(octagon_c_normal_sidewall_prism, "octagon_c_normal_sidewall_gnu_plot.dat"); @@ -573,11 +573,11 @@ int test_helper_functions_on_octagonal_c_prism() { vector3 zhat = make_vector3(0, 0, 1); double normal_sidewall = 0; - geometric_object octagon_c_normal_sidewall_geom_object = make_prism(m, nodes_octagon_c, num_nodes_octagon_c, height_octagon_c, zhat, normal_sidewall); + geometric_object octagon_c_normal_sidewall_geom_object = make_prism(m, nodes_octagon_c, num_nodes_octagon_c, height_octagon_c, zhat); prism *octagon_c_normal_sidewall_prism = octagon_c_normal_sidewall_geom_object.subclass.prism_data; double two_half_degree_sidewall = 2.5 * 2 * K_PI / 360.0; - geometric_object octagon_c_two_half_degree_sidewall_geom_object = make_prism(m, nodes_octagon_c, num_nodes_octagon_c, height_octagon_c, zhat, two_half_degree_sidewall); + geometric_object octagon_c_two_half_degree_sidewall_geom_object = make_slanted_prism(m, nodes_octagon_c, num_nodes_octagon_c, height_octagon_c, zhat, two_half_degree_sidewall); prism *octagon_c_two_half_degree_sidewall_prism = octagon_c_two_half_degree_sidewall_geom_object.subclass.prism_data; int num_tests_normal = 0; @@ -1119,7 +1119,7 @@ int run_unit_tests() { v[3].z = -0.5 * LZ; geometric_object the_block = make_block(m, c, xhat, yhat, zhat, size); - geometric_object the_prism = make_prism(m, v, 4, LZ, zhat, 0.0); + geometric_object the_prism = make_prism(m, v, 4, LZ, zhat); /***************************************************************/ /* with probability P_SHIFT, shift the centers of both block */ @@ -1263,7 +1263,7 @@ int main(int argc, char *argv[]) { } fclose(f); - geometric_object the_prism = make_prism(NULL, vertices_bottom, num_vertices, height, axis, 0.0); + geometric_object the_prism = make_prism(NULL, vertices_bottom, num_vertices, height, axis); prism *prsm = the_prism.subclass.prism_data; prism2gmsh(prsm, "test-prism.pp"); prism2gnuplot(prsm, "test-prism.gp");