Example #1
0
File: hyp.c Project: kanzure/brlcad
/**
 * Given a pointer to a GED database record, and a transformation
 * matrix, determine if this is a valid HYP, and if so, precompute
 * various terms of the formula.
 *
 * Returns -
 * 0  HYP is OK
 * !0 Error in description
 *
 * Implicit return -
 * A struct hyp_specific is created, and its address is stored in
 * stp->st_specific for use by hyp_shot().
 */
int
rt_hyp_prep(struct soltab *stp, struct rt_db_internal *ip, struct rt_i *rtip)
{
    struct rt_hyp_internal *hyp_ip;
    struct hyp_specific *hyp;

    RT_CK_DB_INTERNAL(ip);

    hyp_ip = (struct rt_hyp_internal *)ip->idb_ptr;
    RT_HYP_CK_MAGIC(hyp_ip);

    /* TODO: check that this is a valid hyperboloid (assume it is, for now)  */

    /* set soltab ID */
    stp->st_id = ID_HYP;
    stp->st_meth = &OBJ[ID_HYP];

    hyp =  hyp_internal_to_specific(hyp_ip);
    stp->st_specific = (void *)hyp;

    /* calculate bounding sphere */
    VMOVE(stp->st_center, hyp->hyp_V);
    stp->st_aradius = sqrt((hyp->hyp_c*hyp->hyp_c + 1)*MAGSQ(hyp->hyp_H)
			   + (hyp->hyp_r1*hyp->hyp_r1));
    stp->st_bradius = stp->st_aradius;

    /* calculate bounding RPP */
    if (rt_hyp_bbox(ip, &(stp->st_min), &(stp->st_max), &rtip->rti_tol)) return 1;
    return 0;			/* OK */
}
Example #2
0
File: hyp.c Project: kanzure/brlcad
/**
 * Create a bounding RPP for an hyp
 */
int
rt_hyp_bbox(struct rt_db_internal *ip, point_t *min, point_t *max, const struct bn_tol *UNUSED(tol)) {
    struct rt_hyp_internal *xip;
    vect_t hyp_Au, hyp_B, hyp_An, hyp_Bn, hyp_H;
    vect_t pt1, pt2, pt3, pt4, pt5, pt6, pt7, pt8;
    RT_CK_DB_INTERNAL(ip);
    xip = (struct rt_hyp_internal *)ip->idb_ptr;
    RT_HYP_CK_MAGIC(xip);

    VMOVE(hyp_H, xip->hyp_Hi);
    VUNITIZE(hyp_H);
    VMOVE(hyp_Au, xip->hyp_A);
    VUNITIZE(hyp_Au);
    VCROSS(hyp_B, hyp_Au, hyp_H);

    VSETALL((*min), INFINITY);
    VSETALL((*max), -INFINITY);

    VSCALE(hyp_B, hyp_B, xip->hyp_b);
    VREVERSE(hyp_An, xip->hyp_A);
    VREVERSE(hyp_Bn, hyp_B);

    VADD3(pt1, xip->hyp_Vi, xip->hyp_A, hyp_B);
    VADD3(pt2, xip->hyp_Vi, xip->hyp_A, hyp_Bn);
    VADD3(pt3, xip->hyp_Vi, hyp_An, hyp_B);
    VADD3(pt4, xip->hyp_Vi, hyp_An, hyp_Bn);
    VADD4(pt5, xip->hyp_Vi, xip->hyp_A, hyp_B, xip->hyp_Hi);
    VADD4(pt6, xip->hyp_Vi, xip->hyp_A, hyp_Bn, xip->hyp_Hi);
    VADD4(pt7, xip->hyp_Vi, hyp_An, hyp_B, xip->hyp_Hi);
    VADD4(pt8, xip->hyp_Vi, hyp_An, hyp_Bn, xip->hyp_Hi);

    /* Find the RPP of the rotated axis-aligned hyp bbox - that is,
     * the bounding box the given hyp would have if its height
     * vector were in the positive Z direction. This does not give
     * us an optimal bbox except in the case where the hyp is
     * actually axis aligned to start with, but it's usually
     * at least a bit better than the bounding sphere RPP. */
    VMINMAX((*min), (*max), pt1);
    VMINMAX((*min), (*max), pt2);
    VMINMAX((*min), (*max), pt3);
    VMINMAX((*min), (*max), pt4);
    VMINMAX((*min), (*max), pt5);
    VMINMAX((*min), (*max), pt6);
    VMINMAX((*min), (*max), pt7);
    VMINMAX((*min), (*max), pt8);

    return 0;
}
Example #3
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;
}
Example #4
0
File: hyp.c Project: kanzure/brlcad
/**
 * Returns -
 * -1 failure
 * 0 OK.  *r points to nmgregion that holds this tessellation.
 */
int
rt_hyp_tess(struct nmgregion **r, struct model *m, struct rt_db_internal *ip, const struct rt_tess_tol *ttol, const struct bn_tol *tol)
{
    fastf_t c, dtol, f, mag_a, mag_h, ntol, r1, r2, r3, cprime;
    fastf_t **ellipses = NULL;
    fastf_t theta_new;
    int *pts_dbl, face, i, j, nseg;
    int jj, nell;
    mat_t invRoS;
    mat_t SoR;
    struct rt_hyp_internal *iip;
    struct hyp_specific *xip;
    struct rt_pt_node *pos_a, *pos_b, *pts_a, *pts_b;
    struct shell *s;
    struct faceuse **outfaceuses = NULL;
    struct faceuse *fu_top;
    struct loopuse *lu;
    struct edgeuse *eu;
    struct vertex *vertp[3];
    struct vertex ***vells = (struct vertex ***)NULL;
    vect_t A, Au, B, Bu, Hu, V;
    struct bu_ptbl vert_tab;

    MAT_ZERO(invRoS);
    MAT_ZERO(SoR);

    RT_CK_DB_INTERNAL(ip);
    iip = (struct rt_hyp_internal *)ip->idb_ptr;
    RT_HYP_CK_MAGIC(iip);

    xip = hyp_internal_to_specific(iip);

    /*
     * make sure hyp description is valid
     */

    /* compute |A| |H| */
    mag_a = MAGSQ(xip->hyp_Au);	/* should already be unit vector */
    mag_h = MAGNITUDE(xip->hyp_H);
    c = xip->hyp_c;
    cprime = c / mag_h;
    r1 = xip->hyp_r1;
    r2 = xip->hyp_r2;
    r3 = r1 / c;
    /* Check for |H| > 0, |A| == 1, r1 > 0, r2 > 0, c > 0 */
    if (NEAR_ZERO(mag_h, RT_LEN_TOL)
	|| !NEAR_EQUAL(mag_a, 1.0, RT_LEN_TOL)
	|| r1 <= 0.0 || r2 <= 0.0 || c <= 0.) {
	return 1;		/* BAD */
    }

    /* Check for A.H == 0 */
    f = VDOT(xip->hyp_Au, xip->hyp_H) / mag_h;
    if (! NEAR_ZERO(f, RT_DOT_TOL)) {
	return 1;		/* BAD */
    }

    /* make unit vectors in A, H, and HxA directions */
    VMOVE(Hu, xip->hyp_H);
    VUNITIZE(Hu);
    VMOVE(Au, xip->hyp_Au);
    VCROSS(Bu, Hu, Au);

    dtol = primitive_get_absolute_tolerance(ttol, 2.0 * r2);

    /* To ensure normal tolerance, remain below this angle */
    if (ttol->norm > 0.0)
	ntol = ttol->norm;
    else
	/* tolerate everything */
	ntol = M_PI;

    /*
     * build hyp from 2 hyperbolas
     */

    /* calculate major axis hyperbola */
    BU_ALLOC(pts_a, struct rt_pt_node);

    /* set base, center, and top points */
    pos_a = pts_a;
    VSET(pos_a->p, sqrt((mag_h*mag_h) * (c*c) + (r1*r1)), 0, -mag_h);
    BU_ALLOC(pos_a->next, struct rt_pt_node);
    pos_a = pos_a->next;
    VSET(pos_a->p, r1, 0, 0);
    BU_ALLOC(pos_a->next, struct rt_pt_node);
    pos_a = pos_a->next;
    VSET(pos_a->p, sqrt((mag_h*mag_h) * (c*c) + (r1*r1)), 0, mag_h);
    pos_a->next = NULL;

    /* refine hyp according to tolerances */
    i = 1;
    {
	point_t p0, p1, p2;
	fastf_t mm, len, dist, ang0, ang2;
	vect_t v01, v02; /* vectors from p0->p1 and p0->p2 */
	vect_t nLine, nHyp;
	struct rt_pt_node *add;

	while (i) {
	    pos_a = pts_a;
	    i = 0;
	    while (pos_a->next) {

		VMOVE(p0, pos_a->p);
		VMOVE(p2, pos_a->next->p);
		/* either X or Y will be zero; so adding handles either case */
		mm = (p2[Z] - p0[Z]) / ((p2[X]+p2[Y]) - (p0[X]+p0[Y]));
		if (!ZERO(p0[X])) {
		    p1[X] = fabs(mm*c*r1) / sqrt(mm*mm*c*c - 1.0);
		    p1[Y] = 0.0;
		    p1[Z] = sqrt(p1[X]*p1[X] - r1*r1) / c;
		} else {
		    p1[X] = 0.0;
		    p1[Y] = fabs(mm*r2*r2*c) / sqrt(mm*mm*r2*r2*c*c - r1*r1);
		    p1[Z] = (r3/r2) * sqrt(p1[Y]*p1[Y] - r2*r2);
		}
		if (p0[Z] + p2[Z] < 0) p1[Z] = -p1[Z];

		VSUB2(v01, p1, p0);
		VSUB2(v02, p2, p0);
		VUNITIZE(v02);
		len = VDOT(v01, v02);
		VSCALE(v02, v02, len);
		VSUB2(nLine, v01, v02);
		dist = MAGNITUDE(nLine);
		VUNITIZE(nLine);

		VSET(nHyp, p0[X] / (r1*r1), p0[Y] / (r2*r2), p0[Z] / (r3*r3));
		VUNITIZE(nHyp);
		ang0 = fabs(acos(VDOT(nLine, nHyp)));
		VSET(nHyp, p2[X] / (r1*r1), p2[Y] / (r2*r2), p2[Z] / (r3*r3));
		VUNITIZE(nHyp);
		ang2 = fabs(acos(VDOT(nLine, nHyp)));

		if (dist > dtol || ang0 > ntol || ang2 > ntol) {
		    /* split segment */
		    BU_ALLOC(add, struct rt_pt_node);
		    VMOVE(add->p, p1);
		    add->next = pos_a->next;
		    pos_a->next = add;
		    pos_a = pos_a->next;
		    i = 1;
		}
		pos_a = pos_a->next;
	    }
	}

    }

    /* calculate minor axis hyperbola */
    BU_ALLOC(pts_b, struct rt_pt_node);

    pos_a = pts_a;
    pos_b = pts_b;
    i = 0;
    while (pos_a) {
	pos_b->p[Z] = pos_a->p[Z];
	pos_b->p[X] = 0;
	pos_b->p[Y] = r2 * sqrt(pos_b->p[Z] * pos_b->p[Z]/(r3*r3) + 1.0);
	pos_a = pos_a->next;
	if (pos_a) {
	    BU_ALLOC(pos_b->next, struct rt_pt_node);
	    pos_b = pos_b->next;
	} else {
	    pos_b->next = NULL;
	}
	i++;
    }
Example #5
0
File: hyp.c Project: kanzure/brlcad
int
rt_hyp_plot(struct bu_list *vhead, struct rt_db_internal *incoming, const struct rt_tess_tol *UNUSED(ttol), const struct bn_tol *UNUSED(tol), const struct rt_view_info *UNUSED(info))
{
    int i, j;		/* loop indices */
    struct rt_hyp_internal *hyp_in;
    struct hyp_specific *hyp;
    vect_t majorAxis[8],	/* vector offsets along major axis */
	minorAxis[8],		/* vector offsets along minor axis */
	heightAxis[7],		/* vector offsets for layers */
	Bunit;			/* unit vector along semi-minor axis */
    vect_t ell[16];		/* stores 16 points to draw ellipses */
    vect_t ribs[16][7];		/* assume 7 layers for now */
    fastf_t scale;		/* used to calculate semi-major/minor axes for top/bottom */
    fastf_t cos22_5 = 0.9238795325112867385;
    fastf_t cos67_5 = 0.3826834323650898373;

    BU_CK_LIST_HEAD(vhead);
    RT_CK_DB_INTERNAL(incoming);
    hyp_in = (struct rt_hyp_internal *)incoming->idb_ptr;
    RT_HYP_CK_MAGIC(hyp_in);

    hyp = hyp_internal_to_specific(hyp_in);

    VCROSS(Bunit, hyp->hyp_H, hyp->hyp_Au);
    VUNITIZE(Bunit);

    VMOVE(heightAxis[0], hyp->hyp_H);
    VSCALE(heightAxis[1], heightAxis[0], 0.5);
    VSCALE(heightAxis[2], heightAxis[0], 0.25);
    VSETALL(heightAxis[3], 0);
    VREVERSE(heightAxis[4], heightAxis[2]);
    VREVERSE(heightAxis[5], heightAxis[1]);
    VREVERSE(heightAxis[6], heightAxis[0]);

    for (i = 0; i < 7; i++) {
	/* determine Z height depending on i */
	scale = sqrt(MAGSQ(heightAxis[i])*(hyp->hyp_c * hyp->hyp_c)/(hyp->hyp_r1 * hyp->hyp_r1) + 1);

	/* calculate vectors for offset */
	VSCALE(majorAxis[0], hyp->hyp_Au, hyp->hyp_r1 * scale);
	VSCALE(majorAxis[1], majorAxis[0], cos22_5);
	VSCALE(majorAxis[2], majorAxis[0], M_SQRT1_2);
	VSCALE(majorAxis[3], majorAxis[0], cos67_5);
	VREVERSE(majorAxis[4], majorAxis[3]);
	VREVERSE(majorAxis[5], majorAxis[2]);
	VREVERSE(majorAxis[6], majorAxis[1]);
	VREVERSE(majorAxis[7], majorAxis[0]);

	VSCALE(minorAxis[0], Bunit, hyp->hyp_r2 * scale);
	VSCALE(minorAxis[1], minorAxis[0], cos22_5);
	VSCALE(minorAxis[2], minorAxis[0], M_SQRT1_2);
	VSCALE(minorAxis[3], minorAxis[0], cos67_5);
	VREVERSE(minorAxis[4], minorAxis[3]);
	VREVERSE(minorAxis[5], minorAxis[2]);
	VREVERSE(minorAxis[6], minorAxis[1]);
	VREVERSE(minorAxis[7], minorAxis[0]);

	/* calculate ellipse */
	VADD3(ell[ 0], hyp->hyp_V, heightAxis[i], majorAxis[0]);
	VADD4(ell[ 1], hyp->hyp_V, heightAxis[i], majorAxis[1], minorAxis[3]);
	VADD4(ell[ 2], hyp->hyp_V, heightAxis[i], majorAxis[2], minorAxis[2]);
	VADD4(ell[ 3], hyp->hyp_V, heightAxis[i], majorAxis[3], minorAxis[1]);
	VADD3(ell[ 4], hyp->hyp_V, heightAxis[i], minorAxis[0]);
	VADD4(ell[ 5], hyp->hyp_V, heightAxis[i], majorAxis[4], minorAxis[1]);
	VADD4(ell[ 6], hyp->hyp_V, heightAxis[i], majorAxis[5], minorAxis[2]);
	VADD4(ell[ 7], hyp->hyp_V, heightAxis[i], majorAxis[6], minorAxis[3]);
	VADD3(ell[ 8], hyp->hyp_V, heightAxis[i], majorAxis[7]);
	VADD4(ell[ 9], hyp->hyp_V, heightAxis[i], majorAxis[6], minorAxis[4]);
	VADD4(ell[10], hyp->hyp_V, heightAxis[i], majorAxis[5], minorAxis[5]);
	VADD4(ell[11], hyp->hyp_V, heightAxis[i], majorAxis[4], minorAxis[6]);
	VADD3(ell[12], hyp->hyp_V, heightAxis[i], minorAxis[7]);
	VADD4(ell[13], hyp->hyp_V, heightAxis[i], majorAxis[3], minorAxis[6]);
	VADD4(ell[14], hyp->hyp_V, heightAxis[i], majorAxis[2], minorAxis[5]);
	VADD4(ell[15], hyp->hyp_V, heightAxis[i], majorAxis[1], minorAxis[4]);

	/* draw ellipse */
	RT_ADD_VLIST(vhead, ell[15], BN_VLIST_LINE_MOVE);
	for (j = 0; j < 16; j++) {
	    RT_ADD_VLIST(vhead, ell[j], BN_VLIST_LINE_DRAW);
	}

	/* add ellipse's points to ribs */
	for (j = 0; j < 16; j++) {
	    VMOVE(ribs[j][i], ell[j]);
	}
    }

    /* draw ribs */
    for (i = 0; i < 16; i++) {
	RT_ADD_VLIST(vhead, ribs[i][0], BN_VLIST_LINE_MOVE);
	for (j = 1; j < 7; j++) {
	    RT_ADD_VLIST(vhead, ribs[i][j], BN_VLIST_LINE_DRAW);
	}

    }

    BU_PUT(hyp, struct hyp_specific);

    return 0;
}
Example #6
0
extern "C" void
rt_hyp_brep(ON_Brep **b, const struct rt_db_internal *ip, const struct bn_tol *)
{
    struct rt_hyp_internal *eip;

    RT_CK_DB_INTERNAL(ip);
    eip = (struct rt_hyp_internal *)ip->idb_ptr;
    RT_HYP_CK_MAGIC(eip);

    point_t p1_origin, p2_origin;
    ON_3dPoint plane1_origin, plane2_origin;
    ON_3dVector plane_x_dir, plane_y_dir;

    //  First, find planes corresponding to the top and bottom faces - initially

    vect_t x_dir, y_dir;
    VMOVE(x_dir, eip->hyp_A);
    VCROSS(y_dir, eip->hyp_A, eip->hyp_Hi);
    VREVERSE(y_dir, y_dir);

    VMOVE(p1_origin, eip->hyp_Vi);
    plane1_origin = ON_3dPoint(p1_origin);
    plane_x_dir = ON_3dVector(x_dir);
    plane_y_dir = ON_3dVector(y_dir);
    const ON_Plane hyp_bottom_plane(plane1_origin, plane_x_dir, plane_y_dir);

    VADD2(p2_origin, eip->hyp_Vi, eip->hyp_Hi);
    plane2_origin = ON_3dPoint(p2_origin);
    const ON_Plane hyp_top_plane(plane2_origin, plane_x_dir, plane_y_dir);

    // Next, create ellipses in the planes corresponding to the edges of the hyp

    ON_Ellipse b_ell(hyp_bottom_plane, MAGNITUDE(eip->hyp_A), eip->hyp_b);
    ON_NurbsCurve* bcurve = ON_NurbsCurve::New();
    b_ell.GetNurbForm((*bcurve));
    bcurve->SetDomain(0.0, 1.0);

    ON_Ellipse t_ell(hyp_top_plane, MAGNITUDE(eip->hyp_A), eip->hyp_b);
    ON_NurbsCurve* tcurve = ON_NurbsCurve::New();
    t_ell.GetNurbForm((*tcurve));
    tcurve->SetDomain(0.0, 1.0);

    // Generate the bottom cap
    ON_SimpleArray<ON_Curve*> boundary;
    boundary.Append(ON_Curve::Cast(bcurve));
    ON_PlaneSurface* bp = new ON_PlaneSurface();
    bp->m_plane = hyp_bottom_plane;
    bp->SetDomain(0, -100.0, 100.0);
    bp->SetDomain(1, -100.0, 100.0);
    bp->SetExtents(0, bp->Domain(0));
    bp->SetExtents(1, bp->Domain(1));
    (*b)->m_S.Append(bp);
    const int bsi = (*b)->m_S.Count() - 1;
    ON_BrepFace& bface = (*b)->NewFace(bsi);
    (*b)->NewPlanarFaceLoop(bface.m_face_index, ON_BrepLoop::outer, boundary, true);
    const ON_BrepLoop* bloop = (*b)->m_L.Last();
    bp->SetDomain(0, bloop->m_pbox.m_min.x, bloop->m_pbox.m_max.x);
    bp->SetDomain(1, bloop->m_pbox.m_min.y, bloop->m_pbox.m_max.y);
    bp->SetExtents(0, bp->Domain(0));
    bp->SetExtents(1, bp->Domain(1));
    (*b)->FlipFace(bface);
    (*b)->SetTrimIsoFlags(bface);
    boundary.Empty();
    delete bcurve;

    // Generate the top cap
    boundary.Append(ON_Curve::Cast(tcurve));
    ON_PlaneSurface* tp = new ON_PlaneSurface();
    tp->m_plane = hyp_top_plane;
    tp->SetDomain(0, -100.0, 100.0);
    tp->SetDomain(1, -100.0, 100.0);
    tp->SetExtents(0, bp->Domain(0));
    tp->SetExtents(1, bp->Domain(1));
    (*b)->m_S.Append(tp);
    int tsi = (*b)->m_S.Count() - 1;
    ON_BrepFace& tface = (*b)->NewFace(tsi);
    (*b)->NewPlanarFaceLoop(tface.m_face_index, ON_BrepLoop::outer, boundary, true);
    ON_BrepLoop* tloop = (*b)->m_L.Last();
    tp->SetDomain(0, tloop->m_pbox.m_min.x, tloop->m_pbox.m_max.x);
    tp->SetDomain(1, tloop->m_pbox.m_min.y, tloop->m_pbox.m_max.y);
    tp->SetExtents(0, bp->Domain(0));
    tp->SetExtents(1, bp->Domain(1));
    (*b)->SetTrimIsoFlags(tface);
    delete tcurve;

    //  Now, the hard part.  Need an elliptical hyperbolic NURBS surface.
    //  First step is to create a nurbs curve.

    double MX = eip->hyp_b * eip->hyp_bnr;
    point_t ep1, ep2, ep3;
    VSET(ep1, -eip->hyp_b, 0, 0.5*MAGNITUDE(eip->hyp_Hi));
    VSET(ep2, -MX*eip->hyp_bnr, 0, 0);
    VSET(ep3, -eip->hyp_b, 0, -0.5*MAGNITUDE(eip->hyp_Hi));

    ON_3dPoint onp1 = ON_3dPoint(ep1);
    ON_3dPoint onp2 = ON_3dPoint(ep2);
    ON_3dPoint onp3 = ON_3dPoint(ep3);

    ON_3dPointArray cpts(3);
    cpts.Append(onp1);
    cpts.Append(onp2);
    cpts.Append(onp3);
    ON_BezierCurve *bezcurve = new ON_BezierCurve(cpts);
    bezcurve->MakeRational();
    bezcurve->SetWeight(1, bezcurve->Weight(0)/eip->hyp_bnr);

    ON_NurbsCurve* tnurbscurve = ON_NurbsCurve::New();
    bezcurve->GetNurbForm(*tnurbscurve);
    delete bezcurve;

    ON_3dPoint revpnt1 = ON_3dPoint(0, 0, -0.5*MAGNITUDE(eip->hyp_Hi));
    ON_3dPoint revpnt2 = ON_3dPoint(0, 0, 0.5*MAGNITUDE(eip->hyp_Hi));

    ON_Line revaxis = ON_Line(revpnt1, revpnt2);
    ON_RevSurface* hyp_surf = ON_RevSurface::New();
    hyp_surf->m_curve = tnurbscurve;
    hyp_surf->m_axis = revaxis;
    hyp_surf->m_angle = ON_Interval(0, 2*ON_PI);

    // Get the NURBS form of the surface
    ON_NurbsSurface *hypcurvedsurf = ON_NurbsSurface::New();
    hyp_surf->GetNurbForm(*hypcurvedsurf, 0.0);
    delete hyp_surf;

    for (int i = 0; i < hypcurvedsurf->CVCount(0); i++) {
	for (int j = 0; j < hypcurvedsurf->CVCount(1); j++) {
	    point_t cvpt;
	    ON_4dPoint ctrlpt;
	    hypcurvedsurf->GetCV(i, j, ctrlpt);

	    // Scale and shear
	    vect_t proj_ah;
	    vect_t proj_ax;
	    fastf_t factor;

	    VPROJECT(eip->hyp_A, eip->hyp_Hi, proj_ah, proj_ax);
	    VSET(cvpt, ctrlpt.x * MAGNITUDE(proj_ax)/eip->hyp_b, ctrlpt.y, ctrlpt.z);
	    factor = VDOT(eip->hyp_A, eip->hyp_Hi)>0 ? 1.0 : -1.0;
	    cvpt[2] += factor*cvpt[0]/MAGNITUDE(proj_ax)*MAGNITUDE(proj_ah) + 0.5*MAGNITUDE(eip->hyp_Hi)*ctrlpt.w;

	    // Rotate
	    vect_t Au, Bu, Hu;
	    mat_t R;
	    point_t new_cvpt;

	    VSCALE(Bu, y_dir, 1/MAGNITUDE(y_dir));
	    VSCALE(Hu, eip->hyp_Hi, 1/MAGNITUDE(eip->hyp_Hi));
	    VCROSS(Au, Bu, Hu);
	    VUNITIZE(Au);
	    MAT_IDN(R);
	    VMOVE(&R[0], Au);
	    VMOVE(&R[4], Bu);
	    VMOVE(&R[8], Hu);
	    VEC3X3MAT(new_cvpt, cvpt, R);
	    VMOVE(cvpt, new_cvpt);

	    // Translate
	    vect_t scale_v;
	    VSCALE(scale_v, eip->hyp_Vi, ctrlpt.w);
	    VADD2(cvpt, cvpt, scale_v);
	    ON_4dPoint newpt = ON_4dPoint(cvpt[0], cvpt[1], cvpt[2], ctrlpt.w);
	    hypcurvedsurf->SetCV(i, j, newpt);
	}
    }

    (*b)->m_S.Append(hypcurvedsurf);
    int surfindex = (*b)->m_S.Count();
    ON_BrepFace& face = (*b)->NewFace(surfindex - 1);
    (*b)->FlipFace(face);
    int faceindex = (*b)->m_F.Count();
    (*b)->NewOuterLoop(faceindex-1);

}