/** * 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 */ }
/** * 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; }
/* * 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; }
/** * 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++; }
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; }
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); }