Example #1
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;
}
Example #2
0
/*
 * Default keypoint in model space is established in "pt". Returns
 * GED_ERROR if unable to determine a keypoint, otherwise returns
 * GED_OK.
 */
int
_ged_get_solid_keypoint(struct ged *const gedp,
			fastf_t *const pt,
			const struct rt_db_internal *const ip,
			const fastf_t *const mat)
{
    point_t mpt;

    RT_CK_DB_INTERNAL(ip);

    switch (ip->idb_type) {
	case ID_CLINE:
	    {
		struct rt_cline_internal *cli =
		    (struct rt_cline_internal *)ip->idb_ptr;

		RT_CLINE_CK_MAGIC(cli);

		VMOVE(mpt, cli->v);
		break;
	    }
	case ID_PARTICLE:
	    {
		struct rt_part_internal *part =
		    (struct rt_part_internal *)ip->idb_ptr;

		RT_PART_CK_MAGIC(part);

		VMOVE(mpt, part->part_V);
		break;
	    }
	case ID_PIPE:
	    {
		struct rt_pipe_internal *pipeip;
		struct wdb_pipept *pipe_seg;

		pipeip = (struct rt_pipe_internal *)ip->idb_ptr;

		RT_PIPE_CK_MAGIC(pipeip);

		pipe_seg = BU_LIST_FIRST(wdb_pipept, &pipeip->pipe_segs_head);
		VMOVE(mpt, pipe_seg->pp_coord);
		break;
	    }
	case ID_METABALL:
	    {
		struct rt_metaball_internal *metaball =
		    (struct rt_metaball_internal *)ip->idb_ptr;
		struct wdb_metaballpt *metaballpt;

		RT_METABALL_CK_MAGIC(metaball);

		VSETALL(mpt, 0.0);
		metaballpt = BU_LIST_FIRST(wdb_metaballpt,
					   &metaball->metaball_ctrl_head);
		VMOVE(mpt, metaballpt->coord);
		break;
	    }
	case ID_ARBN:
	    {
		struct rt_arbn_internal *arbn =
		    (struct rt_arbn_internal *)ip->idb_ptr;
		size_t i, j, k;
		int good_vert = 0;

		RT_ARBN_CK_MAGIC(arbn);
		for (i = 0; i < arbn->neqn; i++) {
		    for (j = i + 1; j < arbn->neqn; j++) {
			for (k = j + 1; k < arbn->neqn; k++) {
			    if (!bn_mkpoint_3planes(mpt, arbn->eqn[i],
						    arbn->eqn[j],
						    arbn->eqn[k])) {
				size_t l;

				good_vert = 1;
				for (l = 0; l < arbn->neqn; l++) {
				    if (l == i || l == j || l == k)
					continue;

				    if (DIST_PT_PLANE(mpt,
					arbn->eqn[l]) >
					gedp->ged_wdbp->wdb_tol.dist) {
					good_vert = 0;
					break;
				    }
				}

				if (good_vert)
				    break;
			    }
			}
			if (good_vert)
			    break;
		    }
		    if (good_vert)
			break;
		}

		break;
	    }
	case ID_EBM:
	    {
		struct rt_ebm_internal *ebm =
		    (struct rt_ebm_internal *)ip->idb_ptr;
		point_t pnt;

		RT_EBM_CK_MAGIC(ebm);

		VSETALL(pnt, 0.0);
		MAT4X3PNT(mpt, ebm->mat, pnt);
		break;
	    }
	case ID_BOT:
	    {
		struct rt_bot_internal *bot =
		    (struct rt_bot_internal *)ip->idb_ptr;

		    VMOVE(mpt, bot->vertices);
		break;
	    }
	case ID_DSP:
	    {
		struct rt_dsp_internal *dsp =
		    (struct rt_dsp_internal *)ip->idb_ptr;
		point_t pnt;

		RT_DSP_CK_MAGIC(dsp);

		VSETALL(pnt, 0.0);
		MAT4X3PNT(mpt, dsp->dsp_stom, pnt);
		break;
	    }
	case ID_HF:
	    {
		struct rt_hf_internal *hf =
		    (struct rt_hf_internal *)ip->idb_ptr;

		RT_HF_CK_MAGIC(hf);

		VMOVE(mpt, hf->v);
		break;
	    }
	case ID_VOL:
	    {
		struct rt_vol_internal *vol =
		    (struct rt_vol_internal *)ip->idb_ptr;
		point_t pnt;

		RT_VOL_CK_MAGIC(vol);

		VSETALL(pnt, 0.0);
		MAT4X3PNT(mpt, vol->mat, pnt);
		break;
	    }
	case ID_HALF:
	    {
		struct rt_half_internal *haf =
		    (struct rt_half_internal *)ip->idb_ptr;
		RT_HALF_CK_MAGIC(haf);

		VSCALE(mpt, haf->eqn, haf->eqn[H]);
		break;
	    }
	case ID_ARB8:
	    {
		struct rt_arb_internal *arb =
		    (struct rt_arb_internal *)ip->idb_ptr;
		RT_ARB_CK_MAGIC(arb);

		VMOVE(mpt, arb->pt[0]);
		break;
	    }
	case ID_ELL:
	case ID_SPH:
	    {
		struct rt_ell_internal *ell =
		    (struct rt_ell_internal *)ip->idb_ptr;
		RT_ELL_CK_MAGIC(ell);

		VMOVE(mpt, ell->v);
		break;
	    }
	case ID_SUPERELL:
	    {
		struct rt_superell_internal *superell =
		    (struct rt_superell_internal *)ip->idb_ptr;
		RT_SUPERELL_CK_MAGIC(superell);

		VMOVE(mpt, superell->v);
		break;
	    }
	case ID_TOR:
	    {
		struct rt_tor_internal *tor =
		    (struct rt_tor_internal *)ip->idb_ptr;
		RT_TOR_CK_MAGIC(tor);

		VMOVE(mpt, tor->v);
		break;
	    }
	case ID_TGC:
	case ID_REC:
	    {
		struct rt_tgc_internal *tgc =
		    (struct rt_tgc_internal *)ip->idb_ptr;
		RT_TGC_CK_MAGIC(tgc);

		VMOVE(mpt, tgc->v);
		break;
	    }
	case ID_GRIP:
	    {
		struct rt_grip_internal *gip =
		    (struct rt_grip_internal *)ip->idb_ptr;
		RT_GRIP_CK_MAGIC(gip);
		VMOVE(mpt, gip->center);
		break;
	    }
	case ID_ARS:
	    {
		struct rt_ars_internal *ars =
		    (struct rt_ars_internal *)ip->idb_ptr;
		RT_ARS_CK_MAGIC(ars);

		VMOVE(mpt, &ars->curves[0][0]);
		break;
	    }
	case ID_RPC:
	    {
		struct rt_rpc_internal *rpc =
		    (struct rt_rpc_internal *)ip->idb_ptr;
		RT_RPC_CK_MAGIC(rpc);

		VMOVE(mpt, rpc->rpc_V);
		break;
	    }
	case ID_RHC:
	    {
		struct rt_rhc_internal *rhc =
		    (struct rt_rhc_internal *)ip->idb_ptr;
		RT_RHC_CK_MAGIC(rhc);

		VMOVE(mpt, rhc->rhc_V);
		break;
	    }
	case ID_EPA:
	    {
		struct rt_epa_internal *epa =
		    (struct rt_epa_internal *)ip->idb_ptr;
		RT_EPA_CK_MAGIC(epa);

		VMOVE(mpt, epa->epa_V);
		break;
	    }
	case ID_EHY:
	    {
		struct rt_ehy_internal *ehy =
		    (struct rt_ehy_internal *)ip->idb_ptr;
		RT_EHY_CK_MAGIC(ehy);

		VMOVE(mpt, ehy->ehy_V);
		break;
	    }
	case ID_HYP:
	    {
		struct rt_hyp_internal *hyp =
		    (struct rt_hyp_internal *)ip->idb_ptr;
		RT_HYP_CK_MAGIC(hyp);

		VMOVE(mpt, hyp->hyp_Vi);
		break;
	    }
	case ID_ETO:
	    {
		struct rt_eto_internal *eto =
		    (struct rt_eto_internal *)ip->idb_ptr;
		RT_ETO_CK_MAGIC(eto);

		VMOVE(mpt, eto->eto_V);
		break;
	    }
	case ID_POLY:
	    {
		struct rt_pg_face_internal *_poly;
		struct rt_pg_internal *pg =
		    (struct rt_pg_internal *)ip->idb_ptr;
		RT_PG_CK_MAGIC(pg);

		_poly = pg->poly;
		VMOVE(mpt, _poly->verts);
		break;
	    }
	case ID_SKETCH:
	    {
		struct rt_sketch_internal *skt =
		    (struct rt_sketch_internal *)ip->idb_ptr;
		RT_SKETCH_CK_MAGIC(skt);

		VMOVE(mpt, skt->V);
		break;
	    }
	case ID_EXTRUDE:
	    {
		struct rt_extrude_internal *extr =
		    (struct rt_extrude_internal *)ip->idb_ptr;
		RT_EXTRUDE_CK_MAGIC(extr);

		if (extr->skt && extr->skt->verts) {
		    VJOIN2(mpt, extr->V, extr->skt->verts[0][0], extr->u_vec,
			   extr->skt->verts[0][1], extr->v_vec);
		} else {
		    VMOVE(mpt, extr->V);
		}
		break;
	    }
	case ID_NMG:
	    {
		struct vertex *v;
		struct vertexuse *vu;
		struct edgeuse *eu;
		struct loopuse *lu;
		struct faceuse *fu;
		struct shell *s;
		struct nmgregion *r;
		struct model *m =
		    (struct model *) ip->idb_ptr;
		NMG_CK_MODEL(m);

		/* set default first */
		VSETALL(mpt, 0.0);

		if (BU_LIST_IS_EMPTY(&m->r_hd))
		    break;

		r = BU_LIST_FIRST(nmgregion, &m->r_hd);
		if (!r)
		    break;
		NMG_CK_REGION(r);

		if (BU_LIST_IS_EMPTY(&r->s_hd))
		    break;

		s = BU_LIST_FIRST(shell, &r->s_hd);
		if (!s)
		    break;
		NMG_CK_SHELL(s);

		if (BU_LIST_IS_EMPTY(&s->fu_hd))
		    fu = (struct faceuse *)NULL;
		else
		    fu = BU_LIST_FIRST(faceuse, &s->fu_hd);
		if (fu) {
		    NMG_CK_FACEUSE(fu);
		    lu = BU_LIST_FIRST(loopuse, &fu->lu_hd);
		    NMG_CK_LOOPUSE(lu);
		    if (BU_LIST_FIRST_MAGIC(&lu->down_hd) == NMG_EDGEUSE_MAGIC) {
			eu = BU_LIST_FIRST(edgeuse, &lu->down_hd);
			NMG_CK_EDGEUSE(eu);
			NMG_CK_VERTEXUSE(eu->vu_p);
			v = eu->vu_p->v_p;
		    } else {
			vu = BU_LIST_FIRST(vertexuse, &lu->down_hd);
			NMG_CK_VERTEXUSE(vu);
			v = vu->v_p;
		    }
		    NMG_CK_VERTEX(v);
		    if (!v->vg_p)
			break;
		    VMOVE(mpt, v->vg_p->coord);
		    break;
		}
		if (BU_LIST_IS_EMPTY(&s->lu_hd))
		    lu = (struct loopuse *)NULL;
		else
		    lu = BU_LIST_FIRST(loopuse, &s->lu_hd);
		if (lu) {
		    NMG_CK_LOOPUSE(lu);
		    if (BU_LIST_FIRST_MAGIC(&lu->down_hd) == NMG_EDGEUSE_MAGIC) {
			eu = BU_LIST_FIRST(edgeuse, &lu->down_hd);
			NMG_CK_EDGEUSE(eu);
			NMG_CK_VERTEXUSE(eu->vu_p);
			v = eu->vu_p->v_p;
		    } else {
			vu = BU_LIST_FIRST(vertexuse, &lu->down_hd);
			NMG_CK_VERTEXUSE(vu);
			v = vu->v_p;
		    }
		    NMG_CK_VERTEX(v);
		    if (!v->vg_p)
			break;
		    VMOVE(mpt, v->vg_p->coord);
		    break;
		}
		if (BU_LIST_IS_EMPTY(&s->eu_hd))
		    eu = (struct edgeuse *)NULL;
		else
		    eu = BU_LIST_FIRST(edgeuse, &s->eu_hd);
		if (eu) {
		    NMG_CK_EDGEUSE(eu);
		    NMG_CK_VERTEXUSE(eu->vu_p);
		    v = eu->vu_p->v_p;
		    NMG_CK_VERTEX(v);
		    if (!v->vg_p)
			break;
		    VMOVE(mpt, v->vg_p->coord);
		    break;
		}
		vu = s->vu_p;
		if (vu) {
		    NMG_CK_VERTEXUSE(vu);
		    v = vu->v_p;
		    NMG_CK_VERTEX(v);
		    if (!v->vg_p)
			break;
		    VMOVE(mpt, v->vg_p->coord);
		    break;
		}
	    }
	default:
	    VSETALL(mpt, 0.0);
	    bu_vls_printf(gedp->ged_result_str,
			  "get_solid_keypoint: unrecognized solid type");
	    return GED_ERROR;
    }
    MAT4X3PNT(pt, mat, mpt);
    return GED_OK;
}
static void
tree_solids(union tree *tp, struct tree_bark *tb, int op, struct resource *resp)
{
    RT_CK_TREE(tp);

    switch (tp->tr_op) {
	case OP_NOP:
	    return;

	case OP_SOLID: {
	    struct reg_db_internals *dbint;
	    matp_t mp;
	    long sol_id = 0;
	    struct rt_ell_internal *ell_p;
	    vect_t v;
	    int ret;

	    BU_ALLOC(dbint, struct reg_db_internals);
	    BU_LIST_INIT_MAGIC(&(dbint->l), DBINT_MAGIC);

	    if (tp->tr_a.tu_stp->st_matp)
		mp = tp->tr_a.tu_stp->st_matp;
	    else
		mp = (matp_t)bn_mat_identity;

	    /* Get the internal form of this solid & add it to the list */
	    ret = rt_db_get_internal(&dbint->ip, tp->tr_a.tu_stp->st_dp, tb->dbip, mp, resp);
	    if (ret < 0) {
		bu_log("Failure reading %s object from database.\n", OBJ[sol_id].ft_name);
		return;
	    }

	    RT_CK_DB_INTERNAL(&dbint->ip);
	    dbint->st_p = tp->tr_a.tu_stp;

	    sol_id = dbint->ip.idb_type;

	    if (sol_id < 0) {
		bu_log("Primitive ID %ld out of bounds\n", sol_id);
		bu_bomb("");
	    }


	    if (sol_id != ID_ELL) {

		if (op == OP_UNION)
		    bu_log("Non-ellipse \"union\" primitive of \"%s\" being ignored\n",
			   tb->name);

		if (rdebug&RDEBUG_SHADE)
		    bu_log(" got a primitive type %ld \"%s\".  This primitive ain't no ellipse bucko!\n",
			   sol_id, OBJ[sol_id].ft_name);

		break;
	    }


	    ell_p = (struct rt_ell_internal *)dbint->ip.idb_ptr;

	    if (rdebug&RDEBUG_SHADE)
		bu_log(" got a primitive type %ld \"%s\"\n",
		       sol_id,
		       OBJ[sol_id].ft_name);

	    RT_ELL_CK_MAGIC(ell_p);

	    if (rdebug&RDEBUG_SHADE) {
		VPRINT("point", ell_p->v);
		VPRINT("a", ell_p->a);
		VPRINT("b", ell_p->b);
		VPRINT("c", ell_p->c);
	    }

	    /* create the matrix that maps the coordinate system defined
	     * by the ellipse into model space, and get inverse for use
	     * in the _render() proc
	     */
	    MAT_IDN(mp);
	    VMOVE(v, ell_p->a);	VUNITIZE(v);
	    mp[0] = v[0];	mp[4] = v[1];	mp[8] = v[2];

	    VMOVE(v, ell_p->b);	VUNITIZE(v);
	    mp[1] = v[0];	mp[5] = v[1];	mp[9] = v[2];

	    VMOVE(v, ell_p->c);	VUNITIZE(v);
	    mp[2] = v[0];	mp[6] = v[1];	mp[10] = v[2];

	    MAT_DELTAS_VEC(mp, ell_p->v);

	    MAT_COPY(dbint->ell2model, mp);
	    bn_mat_inv(dbint->model2ell, mp);


	    /* find scaling of gaussian puff in ellipsoid space */
	    VSET(dbint->one_sigma,
		 MAGNITUDE(ell_p->a) / tb->gs->gauss_sigma,
		 MAGNITUDE(ell_p->b) / tb->gs->gauss_sigma,
		 MAGNITUDE(ell_p->c) / tb->gs->gauss_sigma);


	    if (rdebug&RDEBUG_SHADE) {
		VPRINT("sigma", dbint->one_sigma);
	    }
	    BU_LIST_APPEND(tb->l, &(dbint->l));

	    break;
	}
	case OP_UNION:
	    tree_solids(tp->tr_b.tb_left, tb, tp->tr_op, resp);
	    tree_solids(tp->tr_b.tb_right, tb, tp->tr_op, resp);
	    break;

	case OP_NOT: bu_log("Warning: 'Not' region operator in %s\n", tb->name);
	    tree_solids(tp->tr_b.tb_left, tb, tp->tr_op, resp);
	    break;
	case OP_GUARD:bu_log("Warning: 'Guard' region operator in %s\n", tb->name);
	    tree_solids(tp->tr_b.tb_left, tb, tp->tr_op, resp);
	    break;
	case OP_XNOP:bu_log("Warning: 'XNOP' region operator in %s\n", tb->name);
	    tree_solids(tp->tr_b.tb_left, tb, tp->tr_op, resp);
	    break;

	case OP_INTERSECT:
	case OP_SUBTRACT:
	case OP_XOR:
	    /* XXX this can get us in trouble if 1 solid is subtracted
	     * from less than all the "union" solids of the region.
	     */
	    tree_solids(tp->tr_b.tb_left, tb, tp->tr_op, resp);
	    tree_solids(tp->tr_b.tb_right, tb, tp->tr_op, resp);
	    return;

	default:
	    bu_bomb("rt_tree_region_assign: bad op\n");
    }
}