/** * R T _ D S P _ M I R R O R * * Given a pointer to an internal GED database object, mirror the * object's values about the given transformation matrix. */ int rt_dsp_mirror(struct rt_db_internal *ip, register const plane_t plane) { struct rt_dsp_internal *dsp; mat_t mirmat; mat_t rmat; mat_t temp; vect_t nvec; vect_t xvec; vect_t mirror_dir; point_t mirror_pt; fastf_t ang; static point_t origin = {0.0, 0.0, 0.0}; RT_CK_DB_INTERNAL(ip); dsp = (struct rt_dsp_internal *)ip->idb_ptr; RT_EBM_CK_MAGIC(dsp); MAT_IDN(mirmat); VMOVE(mirror_dir, plane); VSCALE(mirror_pt, plane, plane[W]); /* Build mirror transform matrix, for those who need it. */ /* First, perform a mirror down the X axis */ mirmat[0] = -1.0; /* Create the rotation matrix */ VSET(xvec, 1, 0, 0); VCROSS(nvec, xvec, mirror_dir); VUNITIZE(nvec); ang = -acos(VDOT(xvec, mirror_dir)); bn_mat_arb_rot(rmat, origin, nvec, ang*2.0); /* Add the rotation to mirmat */ MAT_COPY(temp, mirmat); bn_mat_mul(mirmat, temp, rmat); /* Add the translation to mirmat */ mirmat[3 + X*4] += mirror_pt[X] * mirror_dir[X]; mirmat[3 + Y*4] += mirror_pt[Y] * mirror_dir[Y]; mirmat[3 + Z*4] += mirror_pt[Z] * mirror_dir[Z]; bn_mat_mul(temp, mirmat, dsp->dsp_mtos); MAT_COPY(dsp->dsp_mtos, temp); return 0; }
/** * Given a pointer to an internal GED database object, mirror the * object's values about the given transformation matrix. */ int rt_half_mirror(struct rt_db_internal *ip, register const plane_t plane) { struct rt_half_internal *half; mat_t mirmat; mat_t rmat; mat_t temp; vect_t nvec; vect_t xvec; vect_t mirror_dir; point_t mirror_pt; fastf_t ang; vect_t n1; vect_t n2; static fastf_t tol_dist_sq = 0.0005 * 0.0005; static point_t origin = {0.0, 0.0, 0.0}; RT_CK_DB_INTERNAL(ip); half = (struct rt_half_internal *)ip->idb_ptr; RT_HALF_CK_MAGIC(half); MAT_IDN(mirmat); VMOVE(mirror_dir, plane); VSCALE(mirror_pt, plane, plane[W]); /* Build mirror transform matrix, for those who need it. */ /* First, perform a mirror down the X axis */ mirmat[0] = -1.0; /* Create the rotation matrix */ VSET(xvec, 1, 0, 0); VCROSS(nvec, xvec, mirror_dir); VUNITIZE(nvec); ang = -acos(VDOT(xvec, mirror_dir)); bn_mat_arb_rot(rmat, origin, nvec, ang*2.0); /* Add the rotation to mirmat */ MAT_COPY(temp, mirmat); bn_mat_mul(mirmat, temp, rmat); /* Add the translation to mirmat */ mirmat[3 + X*4] += mirror_pt[X] * mirror_dir[X]; mirmat[3 + Y*4] += mirror_pt[Y] * mirror_dir[Y]; mirmat[3 + Z*4] += mirror_pt[Z] * mirror_dir[Z]; /* FIXME: this is not using the mirmat we just computed, not clear * it's even right given it's only taking the mirror direction * into account and not the mirror point. */ VMOVE(n1, half->eqn); VCROSS(n2, mirror_dir, n1); VUNITIZE(n2); ang = M_PI_2 - acos(VDOT(n1, mirror_dir)); bn_mat_arb_rot(rmat, origin, n2, ang*2); MAT4X3VEC(half->eqn, rmat, n1); if (!NEAR_EQUAL(VDOT(n1, half->eqn), 1.0, tol_dist_sq)) { point_t ptA; point_t ptB; point_t ptC; vect_t h; fastf_t mag; fastf_t cosa; VSCALE(ptA, n1, half->eqn[H]); VADD2(ptB, ptA, mirror_dir); VSUB2(h, ptB, ptA); mag = MAGNITUDE(h); VUNITIZE(h); cosa = VDOT(h, mirror_dir); VSCALE(ptC, half->eqn, -mag * cosa); VADD2(ptC, ptC, ptA); half->eqn[H] = VDOT(half->eqn, ptC); } return 0; }
/** * Given a pointer to an internal GED database object, mirror the * object's values about the given transformation matrix. */ int rt_ell_mirror(struct rt_db_internal *ip, register const plane_t plane) { struct rt_ell_internal *ell; mat_t mirmat; mat_t rmat; mat_t temp; vect_t nvec; vect_t xvec; vect_t mirror_dir; point_t mirror_pt; fastf_t ang; mat_t mat; point_t pt; vect_t a, b, c; vect_t n; static point_t origin = {0.0, 0.0, 0.0}; RT_CK_DB_INTERNAL(ip); ell = (struct rt_ell_internal *)ip->idb_ptr; RT_ELL_CK_MAGIC(ell); MAT_IDN(mirmat); VMOVE(mirror_dir, plane); VSCALE(mirror_pt, plane, plane[W]); /* Build mirror transform matrix, for those who need it. */ /* First, perform a mirror down the X axis */ mirmat[0] = -1.0; /* Create the rotation matrix */ VSET(xvec, 1, 0, 0); VCROSS(nvec, xvec, mirror_dir); VUNITIZE(nvec); ang = -acos(VDOT(xvec, mirror_dir)); bn_mat_arb_rot(rmat, origin, nvec, ang*2.0); /* Add the rotation to mirmat */ MAT_COPY(temp, mirmat); bn_mat_mul(mirmat, temp, rmat); /* Add the translation to mirmat */ mirmat[3 + X*4] += mirror_pt[X] * mirror_dir[X]; mirmat[3 + Y*4] += mirror_pt[Y] * mirror_dir[Y]; mirmat[3 + Z*4] += mirror_pt[Z] * mirror_dir[Z]; VMOVE(pt, ell->v); MAT4X3PNT(ell->v, mirmat, pt); VMOVE(a, ell->a); VUNITIZE(a); VCROSS(n, mirror_dir, ell->a); VUNITIZE(n); ang = M_PI_2 - acos(VDOT(a, mirror_dir)); bn_mat_arb_rot(mat, origin, n, ang*2); VMOVE(a, ell->a); MAT4X3VEC(ell->a, mat, a); VMOVE(b, ell->b); VUNITIZE(b); VCROSS(n, mirror_dir, ell->b); VUNITIZE(n); ang = M_PI_2 - acos(VDOT(b, mirror_dir)); bn_mat_arb_rot(mat, origin, n, ang*2); VMOVE(b, ell->b); MAT4X3VEC(ell->b, mat, b); VMOVE(c, ell->c); VUNITIZE(c); VCROSS(n, mirror_dir, ell->c); VUNITIZE(n); ang = M_PI_2 - acos(VDOT(c, mirror_dir)); bn_mat_arb_rot(mat, origin, n, ang*2); VMOVE(c, ell->c); MAT4X3VEC(ell->c, mat, c); return 0; }
/** * Given a pointer to an internal GED database object, mirror the * object's values about the given transformation matrix. */ int rt_nurb_mirror(struct rt_db_internal *ip, register const plane_t plane) { struct rt_nurb_internal *nurb; mat_t mirmat; mat_t rmat; mat_t temp; vect_t nvec; vect_t xvec; vect_t mirror_dir; point_t mirror_pt; fastf_t ang; int i; int j; static point_t origin = {0.0, 0.0, 0.0}; RT_CK_DB_INTERNAL(ip); nurb = (struct rt_nurb_internal *)ip->idb_ptr; RT_PG_CK_MAGIC(nurb); MAT_IDN(mirmat); VMOVE(mirror_dir, plane); VSCALE(mirror_pt, plane, plane[W]); /* Build mirror transform matrix, for those who need it. */ /* First, perform a mirror down the X axis */ mirmat[0] = -1.0; /* Create the rotation matrix */ VSET(xvec, 1, 0, 0); VCROSS(nvec, xvec, mirror_dir); VUNITIZE(nvec); ang = -acos(VDOT(xvec, mirror_dir)); bn_mat_arb_rot(rmat, origin, nvec, ang*2.0); /* Add the rotation to mirmat */ MAT_COPY(temp, mirmat); bn_mat_mul(mirmat, temp, rmat); /* Add the translation to mirmat */ mirmat[3 + X*4] += mirror_pt[X] * mirror_dir[X]; mirmat[3 + Y*4] += mirror_pt[Y] * mirror_dir[Y]; mirmat[3 + Z*4] += mirror_pt[Z] * mirror_dir[Z]; for (i=0; i<nurb->nsrf; i++) { fastf_t *ptr; int tmp; int orig_size[2]; int ncoords; int m; int l; /* swap knot vectors between u and v */ ptr = nurb->srfs[i]->u.knots; tmp = nurb->srfs[i]->u.k_size; nurb->srfs[i]->u.knots = nurb->srfs[i]->v.knots; nurb->srfs[i]->u.k_size = nurb->srfs[i]->v.k_size; nurb->srfs[i]->v.knots = ptr; nurb->srfs[i]->v.k_size = tmp; /* swap order */ tmp = nurb->srfs[i]->order[0]; nurb->srfs[i]->order[0] = nurb->srfs[i]->order[1]; nurb->srfs[i]->order[1] = tmp; /* swap mesh size */ orig_size[0] = nurb->srfs[i]->s_size[0]; orig_size[1] = nurb->srfs[i]->s_size[1]; nurb->srfs[i]->s_size[0] = orig_size[1]; nurb->srfs[i]->s_size[1] = orig_size[0]; /* allocate memory for a new control mesh */ ncoords = RT_NURB_EXTRACT_COORDS(nurb->srfs[i]->pt_type); ptr = (fastf_t *)bu_calloc(orig_size[0]*orig_size[1]*ncoords, sizeof(fastf_t), "rt_mirror: ctl mesh ptr"); /* mirror each control point */ for (j=0; j<orig_size[0]*orig_size[1]; j++) { point_t pt; VMOVE(pt, &nurb->srfs[i]->ctl_points[j*ncoords]); MAT4X3PNT(&nurb->srfs[i]->ctl_points[j*ncoords], mirmat, pt); } /* copy mirrored control points into new mesh * while swapping u and v */ m = 0; for (j=0; j<orig_size[0]; j++) { for (l=0; l<orig_size[1]; l++) { VMOVEN(&ptr[(l*orig_size[0]+j)*ncoords], &nurb->srfs[i]->ctl_points[m*ncoords], ncoords); m++; } } /* free old mesh */ bu_free((char *)nurb->srfs[i]->ctl_points, "rt_mirror: ctl points"); /* put new mesh in place */ nurb->srfs[i]->ctl_points = ptr; } return 0; }
int bn_math_cmd(ClientData clientData, Tcl_Interp *interp, int argc, char **argv) { void (*math_func)(); struct bu_vls result; math_func = (void (*)())clientData; /* object-to-function cast */ bu_vls_init(&result); if (math_func == bn_mat_mul) { mat_t o, a, b; if (argc < 3 || bn_decode_mat(a, argv[1]) < 16 || bn_decode_mat(b, argv[2]) < 16) { bu_vls_printf(&result, "usage: %s matA matB", argv[0]); goto error; } bn_mat_mul(o, a, b); bn_encode_mat(&result, o); } else if (math_func == bn_mat_inv || math_func == bn_mat_trn) { mat_t o, a; if (argc < 2 || bn_decode_mat(a, argv[1]) < 16) { bu_vls_printf(&result, "usage: %s mat", argv[0]); goto error; } (*math_func)(o, a); bn_encode_mat(&result, o); } else if (math_func == bn_matXvec) { mat_t m; hvect_t i, o; if (argc < 3 || bn_decode_mat(m, argv[1]) < 16 || bn_decode_hvect(i, argv[2]) < 4) { bu_vls_printf(&result, "usage: %s mat hvect", argv[0]); goto error; } bn_matXvec(o, m, i); bn_encode_hvect(&result, o); } else if (math_func == bn_mat4x3pnt) { mat_t m; point_t i, o; if (argc < 3 || bn_decode_mat(m, argv[1]) < 16 || bn_decode_vect(i, argv[2]) < 3) { bu_vls_printf(&result, "usage: %s mat point", argv[0]); goto error; } bn_mat4x3pnt(o, m, i); bn_encode_vect(&result, o); } else if (math_func == bn_mat4x3vec) { mat_t m; vect_t i, o; if (argc < 3 || bn_decode_mat(m, argv[1]) < 16 || bn_decode_vect(i, argv[2]) < 3) { bu_vls_printf(&result, "usage: %s mat vect", argv[0]); goto error; } bn_mat4x3vec(o, m, i); bn_encode_vect(&result, o); } else if (math_func == bn_hdivide) { hvect_t i; vect_t o; if (argc < 2 || bn_decode_hvect(i, argv[1]) < 4) { bu_vls_printf(&result, "usage: %s hvect", argv[0]); goto error; } bn_hdivide(o, i); bn_encode_vect(&result, o); } else if (math_func == bn_vjoin1) { point_t o; point_t b, d; fastf_t c; if (argc < 4) { bu_vls_printf(&result, "usage: %s pnt scale dir", argv[0]); goto error; } if ( bn_decode_vect(b, argv[1]) < 3) goto error; if (Tcl_GetDouble(interp, argv[2], &c) != TCL_OK) goto error; if ( bn_decode_vect(d, argv[3]) < 3) goto error; VJOIN1( o, b, c, d ); /* bn_vjoin1( o, b, c, d ) */ bn_encode_vect(&result, o); } else if ( math_func == bn_vblend) { point_t a, c, e; fastf_t b, d; if ( argc < 5 ) { bu_vls_printf(&result, "usage: %s scale pnt scale pnt", argv[0]); goto error; } if ( Tcl_GetDouble(interp, argv[1], &b) != TCL_OK) goto error; if ( bn_decode_vect( c, argv[2] ) < 3) goto error; if ( Tcl_GetDouble(interp, argv[3], &d) != TCL_OK) goto error; if ( bn_decode_vect( e, argv[4] ) < 3) goto error; VBLEND2( a, b, c, d, e ) bn_encode_vect( &result, a ); } else if (math_func == bn_mat_ae) { mat_t o; double az, el; if (argc < 3) { bu_vls_printf(&result, "usage: %s azimuth elevation", argv[0]); goto error; } if (Tcl_GetDouble(interp, argv[1], &az) != TCL_OK) goto error; if (Tcl_GetDouble(interp, argv[2], &el) != TCL_OK) goto error; bn_mat_ae(o, (fastf_t)az, (fastf_t)el); bn_encode_mat(&result, o); } else if (math_func == bn_ae_vec) { fastf_t az, el; vect_t v; if (argc < 2 || bn_decode_vect(v, argv[1]) < 3) { bu_vls_printf(&result, "usage: %s vect", argv[0]); goto error; } bn_ae_vec(&az, &el, v); bu_vls_printf(&result, "%g %g", az, el); } else if (math_func == bn_aet_vec) { fastf_t az, el, twist, accuracy; vect_t vec_ae, vec_twist; if (argc < 4 || bn_decode_vect(vec_ae, argv[1]) < 3 || bn_decode_vect(vec_twist, argv[2]) < 3 || sscanf(argv[3], "%lf", &accuracy) < 1) { bu_vls_printf(&result, "usage: %s vec_ae vec_twist accuracy", argv[0]); goto error; } bn_aet_vec(&az, &el, &twist, vec_ae, vec_twist, accuracy); bu_vls_printf(&result, "%g %g %g", az, el, twist); } else if (math_func == bn_mat_angles) { mat_t o; double alpha, beta, ggamma; if (argc < 4) { bu_vls_printf(&result, "usage: %s alpha beta gamma", argv[0]); goto error; } if (Tcl_GetDouble(interp, argv[1], &alpha) != TCL_OK) goto error; if (Tcl_GetDouble(interp, argv[2], &beta) != TCL_OK) goto error; if (Tcl_GetDouble(interp, argv[3], &ggamma) != TCL_OK) goto error; bn_mat_angles(o, alpha, beta, ggamma); bn_encode_mat(&result, o); } else if (math_func == bn_eigen2x2) { fastf_t val1, val2; vect_t vec1, vec2; double a, b, c; if (argc < 4) { bu_vls_printf(&result, "usage: %s a b c", argv[0]); goto error; } if (Tcl_GetDouble(interp, argv[1], &a) != TCL_OK) goto error; if (Tcl_GetDouble(interp, argv[2], &c) != TCL_OK) goto error; if (Tcl_GetDouble(interp, argv[3], &b) != TCL_OK) goto error; bn_eigen2x2(&val1, &val2, vec1, vec2, (fastf_t)a, (fastf_t)b, (fastf_t)c); bu_vls_printf(&result, "%g %g {%g %g %g} {%g %g %g}", val1, val2, V3ARGS(vec1), V3ARGS(vec2)); } else if (math_func == bn_mat_fromto) { mat_t o; vect_t from, to; if (argc < 3 || bn_decode_vect(from, argv[1]) < 3 || bn_decode_vect(to, argv[2]) < 3) { bu_vls_printf(&result, "usage: %s vecFrom vecTo", argv[0]); goto error; } bn_mat_fromto(o, from, to); bn_encode_mat(&result, o); } else if (math_func == bn_mat_xrot || math_func == bn_mat_yrot || math_func == bn_mat_zrot) { mat_t o; double s, c; if (argc < 3) { bu_vls_printf(&result, "usage: %s sinAngle cosAngle", argv[0]); goto error; } if (Tcl_GetDouble(interp, argv[1], &s) != TCL_OK) goto error; if (Tcl_GetDouble(interp, argv[2], &c) != TCL_OK) goto error; (*math_func)(o, s, c); bn_encode_mat(&result, o); } else if (math_func == bn_mat_lookat) { mat_t o; vect_t dir; int yflip; if (argc < 3 || bn_decode_vect(dir, argv[1]) < 3) { bu_vls_printf(&result, "usage: %s dir yflip", argv[0]); goto error; } if (Tcl_GetBoolean(interp, argv[2], &yflip) != TCL_OK) goto error; bn_mat_lookat(o, dir, yflip); bn_encode_mat(&result, o); } else if (math_func == bn_vec_ortho || math_func == bn_vec_perp) { vect_t ov, vec; if (argc < 2 || bn_decode_vect(vec, argv[1]) < 3) { bu_vls_printf(&result, "usage: %s vec", argv[0]); goto error; } (*math_func)(ov, vec); bn_encode_vect(&result, ov); } else if (math_func == bn_mat_scale_about_pt_wrapper) { mat_t o; vect_t v; double scale; int status; if (argc < 3 || bn_decode_vect(v, argv[1]) < 3) { bu_vls_printf(&result, "usage: %s pt scale", argv[0]); goto error; } if (Tcl_GetDouble(interp, argv[2], &scale) != TCL_OK) goto error; bn_mat_scale_about_pt_wrapper(&status, o, v, scale); if (status != 0) { bu_vls_printf(&result, "error performing calculation"); goto error; } bn_encode_mat(&result, o); } else if (math_func == bn_mat_xform_about_pt) { mat_t o, xform; vect_t v; if (argc < 3 || bn_decode_mat(xform, argv[1]) < 16 || bn_decode_vect(v, argv[2]) < 3) { bu_vls_printf(&result, "usage: %s xform pt", argv[0]); goto error; } bn_mat_xform_about_pt(o, xform, v); bn_encode_mat(&result, o); } else if (math_func == bn_mat_arb_rot) { mat_t o; point_t pt; vect_t dir; double angle; if (argc < 4 || bn_decode_vect(pt, argv[1]) < 3 || bn_decode_vect(dir, argv[2]) < 3) { bu_vls_printf(&result, "usage: %s pt dir angle", argv[0]); goto error; } if (Tcl_GetDouble(interp, argv[3], &angle) != TCL_OK) return TCL_ERROR; bn_mat_arb_rot(o, pt, dir, (fastf_t)angle); bn_encode_mat(&result, o); } else if (math_func == quat_mat2quat) { mat_t mat; quat_t quat; if (argc < 2 || bn_decode_mat(mat, argv[1]) < 16) { bu_vls_printf(&result, "usage: %s mat", argv[0]); goto error; } quat_mat2quat(quat, mat); bn_encode_quat(&result, quat); } else if (math_func == quat_quat2mat) { mat_t mat; quat_t quat; if (argc < 2 || bn_decode_quat(quat, argv[1]) < 4) { bu_vls_printf(&result, "usage: %s quat", argv[0]); goto error; } quat_quat2mat(mat, quat); bn_encode_mat(&result, mat); } else if (math_func == bn_quat_distance_wrapper) { quat_t q1, q2; double d; if (argc < 3 || bn_decode_quat(q1, argv[1]) < 4 || bn_decode_quat(q2, argv[2]) < 4) { bu_vls_printf(&result, "usage: %s quatA quatB", argv[0]); goto error; } bn_quat_distance_wrapper(&d, q1, q2); bu_vls_printf(&result, "%g", d); } else if (math_func == quat_double || math_func == quat_bisect || math_func == quat_make_nearest) { quat_t oqot, q1, q2; if (argc < 3 || bn_decode_quat(q1, argv[1]) < 4 || bn_decode_quat(q2, argv[2]) < 4) { bu_vls_printf(&result, "usage: %s quatA quatB", argv[0]); goto error; } (*math_func)(oqot, q1, q2); bn_encode_quat(&result, oqot); } else if (math_func == quat_slerp) { quat_t oq, q1, q2; double d; if (argc < 4 || bn_decode_quat(q1, argv[1]) < 4 || bn_decode_quat(q2, argv[2]) < 4) { bu_vls_printf(&result, "usage: %s quat1 quat2 factor", argv[0]); goto error; } if (Tcl_GetDouble(interp, argv[3], &d) != TCL_OK) goto error; quat_slerp(oq, q1, q2, d); bn_encode_quat(&result, oq); } else if (math_func == quat_sberp) { quat_t oq, q1, qa, qb, q2; double d; if (argc < 6 || bn_decode_quat(q1, argv[1]) < 4 || bn_decode_quat(qa, argv[2]) < 4 || bn_decode_quat(qb, argv[3]) < 4 || bn_decode_quat(q2, argv[4]) < 4) { bu_vls_printf(&result, "usage: %s quat1 quatA quatB quat2 factor", argv[0]); goto error; } if (Tcl_GetDouble(interp, argv[5], &d) != TCL_OK) goto error; quat_sberp(oq, q1, qa, qb, q2, d); bn_encode_quat(&result, oq); } else if (math_func == quat_exp || math_func == quat_log) { quat_t qout, qin; if (argc < 2 || bn_decode_quat(qin, argv[1]) < 4) { bu_vls_printf(&result, "usage: %s quat", argv[0]); goto error; } (*math_func)(qout, qin); bn_encode_quat(&result, qout); } else if (math_func == (void (*)())bn_isect_line3_line3) { double t, u; point_t pt, a; vect_t dir, c; int i; static const struct bn_tol tol = { BN_TOL_MAGIC, 0.005, 0.005*0.005, 1e-6, 1-1e-6 }; if (argc != 5) { bu_vls_printf(&result, "Usage: bn_isect_line3_line3 pt dir pt dir (%d args specified)", argc-1); goto error; } if (bn_decode_vect(pt, argv[1]) < 3) { bu_vls_printf(&result, "bn_isect_line3_line3 no pt: %s\n", argv[0]); goto error; } if (bn_decode_vect(dir, argv[2]) < 3) { bu_vls_printf(&result, "bn_isect_line3_line3 no dir: %s\n", argv[0]); goto error; } if (bn_decode_vect(a, argv[3]) < 3) { bu_vls_printf(&result, "bn_isect_line3_line3 no a pt: %s\n", argv[0]); goto error; } if (bn_decode_vect(c, argv[4]) < 3) { bu_vls_printf(&result, "bn_isect_line3_line3 no c dir: %s\n", argv[0]); goto error; } i = bn_isect_line3_line3(&t, &u, pt, dir, a, c, &tol); if (i != 1) { bu_vls_printf(&result, "bn_isect_line3_line3 no intersection: %s\n", argv[0]); goto error; } VJOIN1(a, pt, t, dir); bn_encode_vect(&result, a); } else if (math_func == (void (*)())bn_isect_line2_line2) { double dist[2]; point_t pt, a; vect_t dir, c; int i; static const struct bn_tol tol = { BN_TOL_MAGIC, 0.005, 0.005*0.005, 1e-6, 1-1e-6 }; if (argc != 5) { bu_vls_printf(&result, "Usage: bn_isect_line2_line2 pt dir pt dir (%d args specified)", argc-1); goto error; } /* i = bn_isect_line2_line2 {0 0} {1 0} {1 1} {0 -1} */ VSETALL(pt, 0.0); VSETALL(dir, 0.0); VSETALL(a, 0.0); VSETALL(c, 0.0); if (bn_decode_vect(pt, argv[1]) < 2) { bu_vls_printf(&result, "bn_isect_line2_line2 no pt: %s\n", argv[0]); goto error; } if (bn_decode_vect(dir, argv[2]) < 2) { bu_vls_printf(&result, "bn_isect_line2_line2 no dir: %s\n", argv[0]); goto error; } if (bn_decode_vect(a, argv[3]) < 2) { bu_vls_printf(&result, "bn_isect_line2_line2 no a pt: %s\n", argv[0]); goto error; } if (bn_decode_vect(c, argv[4]) < 2) { bu_vls_printf(&result, "bn_isect_line2_line2 no c dir: %s\n", argv[0]); goto error; } i = bn_isect_line2_line2(dist, pt, dir, a, c, &tol); if (i != 1) { bu_vls_printf(&result, "bn_isect_line2_line2 no intersection: %s\n", argv[0]); goto error; } VJOIN1(a, pt, dist[0], dir); bu_vls_printf(&result, "%g %g", a[0], a[1]); } else { bu_vls_printf(&result, "libbn/bn_tcl.c: math function %s not supported yet\n", argv[0]); goto error; } Tcl_AppendResult(interp, bu_vls_addr(&result), (char *)NULL); bu_vls_free(&result); return TCL_OK; error: Tcl_AppendResult(interp, bu_vls_addr(&result), (char *)NULL); bu_vls_free(&result); return TCL_ERROR; }
/* * Returns - * -2 unknown keyword * -1 error in processing keyword * 0 OK */ int multi_words( char *words[], int nwords ) { if ( strcmp( words[0], "rot" ) == 0 ) { mat_t mat; /* Expects rotations rx, ry, rz, in degrees */ if ( nwords < 4 ) return(-1); MAT_IDN( mat ); bn_mat_angles( mat, atof( words[1] ), atof( words[2] ), atof( words[3] ) ); out_mat( mat, stdout ); return(0); } if ( strcmp( words[0], "xlate" ) == 0 ) { mat_t mat; if ( nwords < 4 ) return(-1); /* Expects translations tx, ty, tz */ MAT_IDN( mat ); MAT_DELTAS( mat, atof( words[1] ), atof( words[2] ), atof( words[3] ) ); out_mat( mat, stdout ); return(0); } if ( strcmp( words[0], "rot_at" ) == 0 ) { mat_t mat; mat_t mat1; mat_t mat2; mat_t mat3; /* JG - Expects x, y, z, rx, ry, rz */ /* Translation back to the origin by (-x, -y, -z) */ /* is done first, then the rotation, and finally */ /* back into the original position by (+x, +y, +z). */ if ( nwords < 7 ) return(-1); MAT_IDN( mat1 ); MAT_IDN( mat2 ); MAT_IDN( mat3 ); MAT_DELTAS( mat1, -atof( words[1] ), -atof( words[2] ), -atof( words[3] ) ); bn_mat_angles( mat2, atof( words[4] ), atof( words[5] ), atof( words[6] ) ); MAT_DELTAS( mat3, atof( words[1] ), atof( words[2] ), atof( words[3] ) ); bn_mat_mul( mat, mat2, mat1 ); bn_mat_mul2( mat3, mat ); out_mat( mat, stdout ); return(0); } if ( strcmp( words[0], "orient" ) == 0 ) { register int i; mat_t mat; double args[8]; /* Expects tx, ty, tz, rx, ry, rz, [scale]. */ /* All rotation is done first, then translation */ /* Note: word[0] and args[0] are the keyword */ if ( nwords < 6+1 ) return(-1); for ( i=1; i<6+1; i++ ) args[i] = 0; args[7] = 1.0; /* optional arg, default to 1 */ for ( i=1; i<nwords; i++ ) args[i] = atof( words[i] ); MAT_IDN( mat ); bn_mat_angles( mat, args[4], args[5], args[6] ); MAT_DELTAS( mat, args[1], args[2], args[3] ); if ( NEAR_ZERO( args[7], VDIVIDE_TOL ) ) { /* Nearly zero, signal error */ fprintf(stderr, "Orient scale arg is near zero ('%s')\n", words[7] ); return(-1); } else { mat[15] = 1 / args[7]; } out_mat( mat, stdout ); return(0); } if ( strcmp( words[0], "ae" ) == 0 ) { mat_t mat; fastf_t az, el; if ( nwords < 3 ) return(-1); /* Expects azimuth, elev, optional twist */ az = atof(words[1]); el = atof(words[2]); #if 0 if ( nwords == 3 ) twist = 0.0; else twist = atof(words[3]); #endif MAT_IDN( mat ); /* XXX does not take twist, for now XXX */ bn_mat_ae( mat, az, el ); out_mat( mat, stdout ); return(0); } if ( strcmp( words[0], "arb_rot_pt" ) == 0 ) { mat_t mat; point_t pt1, pt2; vect_t dir; fastf_t ang; if ( nwords < 1+3+3+1 ) return(-1); /* Expects point1, point2, angle */ VSET( pt1, atof(words[1]), atof(words[2]), atof(words[3]) ); VSET( pt2, atof(words[4]), atof(words[5]), atof(words[6]) ); ang = atof(words[7]) * bn_degtorad; VSUB2( dir, pt2, pt2 ); VUNITIZE(dir); MAT_IDN( mat ); bn_mat_arb_rot( mat, pt1, dir, ang ); out_mat( mat, stdout ); return(0); } if ( strcmp( words[0], "arb_rot_dir" ) == 0 ) { mat_t mat; point_t pt1; vect_t dir; fastf_t ang; if ( nwords < 1+3+3+1 ) return(-1); /* Expects point1, dir, angle */ VSET( pt1, atof(words[1]), atof(words[2]), atof(words[3]) ); VSET( dir, atof(words[4]), atof(words[5]), atof(words[6]) ); ang = atof(words[7]) * bn_degtorad; VUNITIZE(dir); MAT_IDN( mat ); bn_mat_arb_rot( mat, pt1, dir, ang ); out_mat( mat, stdout ); return(0); } if ( strcmp( words[0], "quat" ) == 0 ) { mat_t mat; quat_t quat; /* Usage: quat x, y, z, w */ if ( nwords < 5 ) return -1; QSET( quat, atof(words[1]), atof(words[2]), atof(words[3]), atof(words[4]) ); quat_quat2mat( mat, quat ); out_mat( mat, stdout); return 0; } if ( strcmp( words[0], "fromto" ) == 0 ) { mat_t mat; point_t cur; point_t next; vect_t from; vect_t to; /* Usage: fromto +Z cur_xyz next_xyz */ if ( nwords < 8 ) return -1; if ( strcmp( words[1], "+X" ) == 0 ) { VSET( from, 1, 0, 0 ); } else if ( strcmp( words[1], "-X" ) == 0 ) { VSET( from, -1, 0, 0 ); } else if ( strcmp( words[1], "+Y" ) == 0 ) { VSET( from, 0, 1, 0 ); } else if ( strcmp( words[1], "-Y" ) == 0 ) { VSET( from, 0, -1, 0 ); } else if ( strcmp( words[1], "+Z" ) == 0 ) { VSET( from, 0, 0, 1 ); } else if ( strcmp( words[1], "-Z" ) == 0 ) { VSET( from, 0, 0, -1 ); } else { fprintf(stderr, "fromto '%s' is not +/-XYZ\n", words[1]); return -1; } VSET( cur, atof(words[2]), atof(words[3]), atof(words[4]) ); VSET( next, atof(words[5]), atof(words[6]), atof(words[7]) ); VSUB2( to, next, cur ); VUNITIZE(to); bn_mat_fromto( mat, from, to ); /* Check to see if it worked. */ { vect_t got; MAT4X3VEC( got, mat, from ); if ( VDOT( got, to ) < 0.9 ) { bu_log("\ntabsub ERROR: At t=%s, bn_mat_fromto failed!\n", chanwords[0] ); VPRINT("\tfrom", from); VPRINT("\tto", to); VPRINT("\tgot", got); } } out_mat( mat, stdout ); return 0; } return(-2); /* Unknown keyword */ }
/* * This routine is called (at prep time) * once for each region which uses this shader. * Any shader-specific initialization should be done here. * * Returns: * 1 success * 0 success, but delete region * -1 failure */ HIDDEN int bbd_setup(struct region *rp, struct bu_vls *matparm, void **dpp, const struct mfuncs *mfp, struct rt_i *rtip) { register struct bbd_specific *bbd_sp; struct rt_db_internal intern; struct rt_tgc_internal *tgc; int s; mat_t mat; struct bbd_img *bi; double angle; vect_t vtmp; int img_num; vect_t vv; /* check the arguments */ RT_CHECK_RTI(rtip); BU_CK_VLS(matparm); RT_CK_REGION(rp); if (rdebug&RDEBUG_SHADE) bu_log("bbd_setup(%s)\n", rp->reg_name); RT_CK_TREE(rp->reg_treetop); if (rp->reg_treetop->tr_a.tu_op != OP_SOLID) { bu_log("--- Warning: Region %s shader %s", rp->reg_name, mfp->mf_name); bu_bomb("Shader should be used on region of single (rec/rcc) primitive\n"); } RT_CK_SOLTAB(rp->reg_treetop->tr_a.tu_stp); if (rp->reg_treetop->tr_a.tu_stp->st_id != ID_REC) { bu_log("--- Warning: Region %s shader %s", rp->reg_name, mfp->mf_name); bu_log("Shader should be used on region of single REC/RCC primitive %d\n", rp->reg_treetop->tr_a.tu_stp->st_id); bu_bomb("oops\n"); } /* Get memory for the shader parameters and shader-specific data */ BU_GET(bbd_sp, struct bbd_specific); *dpp = bbd_sp; /* initialize the default values for the shader */ memcpy(bbd_sp, &bbd_defaults, sizeof(struct bbd_specific)); bu_vls_init(&bbd_sp->img_filename); BU_LIST_INIT(&bbd_sp->imgs); bbd_sp->rtip = rtip; /* because new_image() needs this */ bbd_sp->img_count = 0; /* parse the user's arguments for this use of the shader. */ if (bu_struct_parse(matparm, bbd_parse_tab, (char *)bbd_sp, NULL) < 0) return -1; if (bbd_sp->img_count > MAX_IMAGES) { bu_log("too many images (%zu) in shader for %s sb < %d\n", bbd_sp->img_count, rp->reg_name, MAX_IMAGES); bu_bomb("excessive image count\n"); } MAT_IDN(mat); RT_DB_INTERNAL_INIT(&intern); s = rt_db_get_internal(&intern, rp->reg_treetop->tr_a.tu_stp->st_dp, rtip->rti_dbip, mat, &rt_uniresource); if (intern.idb_minor_type != ID_TGC && intern.idb_minor_type != ID_REC) { bu_log("What did I get? %d\n", intern.idb_minor_type); } if (s < 0) { bu_log("%s:%d didn't get internal", __FILE__, __LINE__); bu_bomb(""); } tgc = (struct rt_tgc_internal *)intern.idb_ptr; RT_TGC_CK_MAGIC(tgc); angle = M_PI / (double)bbd_sp->img_count; img_num = 0; VMOVE(vv, tgc->h); VUNITIZE(vv); for (BU_LIST_FOR(bi, bbd_img, &bbd_sp->imgs)) { static const point_t o = VINIT_ZERO; bn_mat_arb_rot(mat, o, vv, angle*img_num); /* compute plane equation */ MAT4X3VEC(bi->img_plane, mat, tgc->a); VUNITIZE(bi->img_plane); bi->img_plane[H] = VDOT(tgc->v, bi->img_plane); MAT4X3VEC(vtmp, mat, tgc->b); VADD2(bi->img_origin, tgc->v, vtmp); /* image origin in 3d space */ /* calculate image u vector */ VREVERSE(bi->img_x, vtmp); VUNITIZE(bi->img_x); bi->img_xlen = MAGNITUDE(vtmp) * 2; /* calculate image v vector */ VMOVE(bi->img_y, tgc->h); VUNITIZE(bi->img_y); bi->img_ylen = MAGNITUDE(tgc->h); if (rdebug&RDEBUG_SHADE) { HPRINT("\nimg_plane", bi->img_plane); VPRINT("vtmp", vtmp); VPRINT("img_origin", bi->img_origin); bu_log("img_xlen:%g ", bi->img_xlen); VPRINT("img_x", bi->img_x); bu_log("img_ylen:%g ", bi->img_ylen); VPRINT("img_y", bi->img_y); } img_num++; } rt_db_free_internal(&intern); if (rdebug&RDEBUG_SHADE) { bu_struct_print(" Parameters:", bbd_print_tab, (char *)bbd_sp); } return 1; }
/** * Given a pointer to an internal GED database object, mirror the * object's values about the given transformation matrix. */ int rt_arbn_mirror(struct rt_db_internal *ip, register const plane_t plane) { struct rt_arbn_internal *arbn; size_t i; mat_t mirmat; mat_t rmat; mat_t temp; vect_t nvec; vect_t xvec; vect_t mirror_dir; point_t mirror_pt; fastf_t ang; static point_t origin = {0.0, 0.0, 0.0}; RT_CK_DB_INTERNAL(ip); arbn = (struct rt_arbn_internal *)ip->idb_ptr; RT_ARBN_CK_MAGIC(arbn); MAT_IDN(mirmat); VMOVE(mirror_dir, plane); VSCALE(mirror_pt, plane, plane[W]); /* Build mirror transform matrix, for those who need it. */ /* First, perform a mirror down the X axis */ mirmat[0] = -1.0; /* Create the rotation matrix */ VSET(xvec, 1, 0, 0); VCROSS(nvec, xvec, mirror_dir); VUNITIZE(nvec); ang = -acos(VDOT(xvec, mirror_dir)); bn_mat_arb_rot(rmat, origin, nvec, ang*2.0); /* Add the rotation to mirmat */ MAT_COPY(temp, mirmat); bn_mat_mul(mirmat, temp, rmat); /* Add the translation to mirmat */ mirmat[3 + X*4] += mirror_pt[X] * mirror_dir[X]; mirmat[3 + Y*4] += mirror_pt[Y] * mirror_dir[Y]; mirmat[3 + Z*4] += mirror_pt[Z] * mirror_dir[Z]; for (i=0; i<arbn->neqn; i++) { point_t orig_pt; point_t pt; vect_t norm; fastf_t factor; /* unitize the plane equation first */ factor = 1.0 / MAGNITUDE(arbn->eqn[i]); VSCALE(arbn->eqn[i], arbn->eqn[i], factor); arbn->eqn[i][W] = arbn->eqn[i][W] * factor; /* Pick a point on the original halfspace */ VSCALE(orig_pt, arbn->eqn[i], arbn->eqn[i][W]); /* Transform the point, and the normal */ MAT4X3VEC(norm, mirmat, arbn->eqn[i]); MAT4X3PNT(pt, mirmat, orig_pt); /* Measure new distance from origin to new point */ VUNITIZE(norm); VMOVE(arbn->eqn[i], norm); arbn->eqn[i][W] = VDOT(pt, norm); } return 0; }
/** * Given a pointer to an internal GED database object, mirror the * object's values about the given transformation matrix. */ int rt_bot_mirror(struct rt_db_internal *ip, register const plane_t plane) { struct rt_bot_internal *bot; mat_t mirmat; mat_t rmat; mat_t temp; vect_t nvec; vect_t xvec; vect_t mirror_dir; point_t mirror_pt; fastf_t ang; size_t i; static point_t origin = {0.0, 0.0, 0.0}; RT_CK_DB_INTERNAL(ip); bot = (struct rt_bot_internal *)ip->idb_ptr; RT_BOT_CK_MAGIC(bot); MAT_IDN(mirmat); VMOVE(mirror_dir, plane); VSCALE(mirror_pt, plane, plane[W]); /* Build mirror transform matrix, for those who need it. */ /* First, perform a mirror down the X axis */ mirmat[0] = -1.0; /* Create the rotation matrix */ VSET(xvec, 1, 0, 0); VCROSS(nvec, xvec, mirror_dir); VUNITIZE(nvec); ang = -acos(VDOT(xvec, mirror_dir)); bn_mat_arb_rot(rmat, origin, nvec, ang*2.0); /* Add the rotation to mirmat */ MAT_COPY(temp, mirmat); bn_mat_mul(mirmat, temp, rmat); /* Add the translation to mirmat */ mirmat[3 + X*4] += mirror_pt[X] * mirror_dir[X]; mirmat[3 + Y*4] += mirror_pt[Y] * mirror_dir[Y]; mirmat[3 + Z*4] += mirror_pt[Z] * mirror_dir[Z]; /* mirror each vertex */ for (i=0; i<bot->num_vertices; i++) { point_t pt; VMOVE(pt, &bot->vertices[i*3]); MAT4X3PNT(&bot->vertices[i*3], mirmat, pt); } /* Reverse each faces' order */ for (i=0; i<bot->num_faces; i++) { int save_face = bot->faces[i*3]; bot->faces[i*3] = bot->faces[i*3 + Z]; bot->faces[i*3 + Z] = save_face; } /* fix normals */ for (i=0; i<bot->num_normals; i++) { vectp_t np = &bot->normals[i*3]; vect_t n1; vect_t n2; mat_t mat; VMOVE(n1, np); VCROSS(n2, mirror_dir, n1); VUNITIZE(n2); ang = M_PI_2 - acos(VDOT(n1, mirror_dir)); bn_mat_arb_rot(mat, origin, n2, ang*2); MAT4X3VEC(np, mat, n1); } return 0; }
/** * R T _ A R S _ M I R R O R * * Given a pointer to an internal GED database object, mirror the * object's values about the given transformation matrix. */ int rt_ars_mirror(struct rt_db_internal *ip, register const plane_t plane) { struct rt_ars_internal *ars; mat_t mirmat; mat_t rmat; mat_t temp; vect_t nvec; vect_t xvec; vect_t mirror_dir; point_t mirror_pt; fastf_t ang; size_t i; size_t j; fastf_t *tmp_curve; static point_t origin = {0.0, 0.0, 0.0}; RT_CK_DB_INTERNAL(ip); ars = (struct rt_ars_internal *)ip->idb_ptr; RT_ARS_CK_MAGIC(ars); MAT_IDN(mirmat); VMOVE(mirror_dir, plane); VSCALE(mirror_pt, plane, plane[W]); /* Build mirror transform matrix, for those who need it. */ /* First, perform a mirror down the X axis */ mirmat[0] = -1.0; /* Create the rotation matrix */ VSET(xvec, 1, 0, 0); VCROSS(nvec, xvec, mirror_dir); VUNITIZE(nvec); ang = -acos(VDOT(xvec, mirror_dir)); bn_mat_arb_rot(rmat, origin, nvec, ang*2.0); /* Add the rotation to mirmat */ MAT_COPY(temp, mirmat); bn_mat_mul(mirmat, temp, rmat); /* Add the translation to mirmat */ mirmat[3 + X*4] += mirror_pt[X] * mirror_dir[X]; mirmat[3 + Y*4] += mirror_pt[Y] * mirror_dir[Y]; mirmat[3 + Z*4] += mirror_pt[Z] * mirror_dir[Z]; /* mirror each vertex */ for (i=0; i<ars->ncurves; i++) { for (j=0; j<ars->pts_per_curve; j++) { point_t pt; VMOVE(pt, &ars->curves[i][j*3]); MAT4X3PNT(&ars->curves[i][j*3], mirmat, pt); } } /* now reverse order of vertices in each curve */ tmp_curve = (fastf_t *)bu_calloc(3*ars->pts_per_curve, sizeof(fastf_t), "rt_mirror: tmp_curve"); for (i=0; i<ars->ncurves; i++) { /* reverse vertex order */ for (j=0; j<ars->pts_per_curve; j++) { VMOVE(&tmp_curve[(ars->pts_per_curve-j-1)*3], &ars->curves[i][j*3]); } /* now copy back */ memcpy(ars->curves[i], tmp_curve, ars->pts_per_curve*3*sizeof(fastf_t)); } bu_free((char *)tmp_curve, "rt_mirror: tmp_curve"); return 0; }