/** * R T _ P G _ P L O T _ P O L Y * * Convert to vlist, draw as polygons. */ int rt_pg_plot_poly(struct bu_list *vhead, struct rt_db_internal *ip, const struct rt_tess_tol *UNUSED(ttol), const struct bn_tol *UNUSED(tol)) { size_t i; size_t p; /* current polygon number */ struct rt_pg_internal *pgp; BU_CK_LIST_HEAD(vhead); RT_CK_DB_INTERNAL(ip); pgp = (struct rt_pg_internal *)ip->idb_ptr; RT_PG_CK_MAGIC(pgp); for (p = 0; p < pgp->npoly; p++) { struct rt_pg_face_internal *pp; vect_t aa, bb, norm; pp = &pgp->poly[p]; if (pp->npts < 3) continue; VSUB2(aa, &pp->verts[3*(0)], &pp->verts[3*(1)]); VSUB2(bb, &pp->verts[3*(0)], &pp->verts[3*(2)]); VCROSS(norm, aa, bb); VUNITIZE(norm); RT_ADD_VLIST(vhead, norm, BN_VLIST_POLY_START); RT_ADD_VLIST(vhead, &pp->verts[3*(pp->npts-1)], BN_VLIST_POLY_MOVE); for (i=0; i < pp->npts-1; i++) { RT_ADD_VLIST(vhead, &pp->verts[3*i], BN_VLIST_POLY_DRAW); } RT_ADD_VLIST(vhead, &pp->verts[3*(pp->npts-1)], BN_VLIST_POLY_END); } return 0; /* OK */ }
/** * R T _ P G _ I F R E E * * Free the storage associated with the rt_db_internal version of this solid. */ void rt_pg_ifree(struct rt_db_internal *ip) { struct rt_pg_internal *pgp; size_t i; RT_CK_DB_INTERNAL(ip); pgp = (struct rt_pg_internal *)ip->idb_ptr; RT_PG_CK_MAGIC(pgp); /* * Free storage for each polygon */ for (i=0; i < pgp->npoly; i++) { bu_free((char *)pgp->poly[i].verts, "pg verts[]"); bu_free((char *)pgp->poly[i].norms, "pg norms[]"); } if (pgp->npoly) bu_free((char *)pgp->poly, "pg poly[]"); pgp->magic = 0; /* sanity */ pgp->npoly = 0; bu_free((char *)pgp, "pg ifree"); ip->idb_ptr = GENPTR_NULL; /* sanity */ }
/** * R T _ P G _ P L O T * * Calculate the bounding RPP for a poly */ int rt_pg_bbox(struct rt_db_internal *ip, point_t *min, point_t *max, const struct bn_tol *UNUSED(tol)) { struct rt_pg_internal *pgp; size_t i; size_t p; pgp = (struct rt_pg_internal *)ip->idb_ptr; RT_PG_CK_MAGIC(pgp); VSETALL((*min), INFINITY); VSETALL((*max), -INFINITY); for (p = 0; p < pgp->npoly; p++) { vect_t work[3]; VMOVE(work[0], &pgp->poly[p].verts[0*3]); VMINMAX((*min), (*max), work[0]); VMOVE(work[1], &pgp->poly[p].verts[1*3]); VMINMAX((*min), (*max), work[1]); for (i=2; i < pgp->poly[p].npts; i++) { VMOVE(work[2], &pgp->poly[p].verts[i*3]); VMINMAX((*min), (*max), work[2]); /* Chop off a triangle, and continue */ VMOVE(work[1], work[2]); } } return 0; /* OK */ }
/** * R T _ P G _ P L O T */ int rt_pg_plot(struct bu_list *vhead, struct rt_db_internal *ip, const struct rt_tess_tol *UNUSED(ttol), const struct bn_tol *UNUSED(tol), const struct rt_view_info *UNUSED(info)) { size_t i; size_t p; /* current polygon number */ struct rt_pg_internal *pgp; BU_CK_LIST_HEAD(vhead); RT_CK_DB_INTERNAL(ip); pgp = (struct rt_pg_internal *)ip->idb_ptr; RT_PG_CK_MAGIC(pgp); for (p = 0; p < pgp->npoly; p++) { struct rt_pg_face_internal *pp; pp = &pgp->poly[p]; RT_ADD_VLIST(vhead, &pp->verts[3*(pp->npts-1)], BN_VLIST_LINE_MOVE); for (i=0; i < pp->npts; i++) { RT_ADD_VLIST(vhead, &pp->verts[3*i], BN_VLIST_LINE_DRAW); } } return 0; /* OK */ }
/** * R T _ P G _ P R E P * * This routine is used to prepare a list of planar faces for * being shot at by the triangle routines. * * Process a PG, which is represented as a vector * from the origin to the first point, and many vectors * from the first point to the remaining points. * */ int rt_pg_prep(struct soltab *stp, struct rt_db_internal *ip, struct rt_i *rtip) { struct rt_pg_internal *pgp; size_t i; size_t p; pgp = (struct rt_pg_internal *)ip->idb_ptr; RT_PG_CK_MAGIC(pgp); if (rt_pg_bbox(ip, &(stp->st_min), &(stp->st_max), &rtip->rti_tol)) return 1; for (p = 0; p < pgp->npoly; p++) { vect_t work[3]; VMOVE(work[0], &pgp->poly[p].verts[0*3]); VMOVE(work[1], &pgp->poly[p].verts[1*3]); for (i=2; i < pgp->poly[p].npts; i++) { VMOVE(work[2], &pgp->poly[p].verts[i*3]); /* output a face */ (void)rt_pgface(stp, work[0], work[1], work[2], &rtip->rti_tol); /* Chop off a triangle, and continue */ VMOVE(work[1], work[2]); } } if (stp->st_specific == (genptr_t)0) { bu_log("pg(%s): no faces\n", stp->st_name); return -1; /* BAD */ } { fastf_t dx, dy, dz; fastf_t f; VADD2SCALE(stp->st_center, stp->st_max, stp->st_min, 0.5); dx = (stp->st_max[X] - stp->st_min[X])/2; f = dx; dy = (stp->st_max[Y] - stp->st_min[Y])/2; if (dy > f) f = dy; dz = (stp->st_max[Z] - stp->st_min[Z])/2; if (dz > f) f = dz; stp->st_aradius = f; stp->st_bradius = sqrt(dx*dx + dy*dy + dz*dz); } return 0; /* OK */ }
/** * R T _ P G _ D E S C R I B E * * Make human-readable formatted presentation of this solid. * First line describes type of solid. * Additional lines are indented one tab, and give parameter values. */ int rt_pg_describe(struct bu_vls *str, const struct rt_db_internal *ip, int verbose, double mm2local) { size_t i, j; struct rt_pg_internal *pgp = (struct rt_pg_internal *)ip->idb_ptr; char buf[256] = {0}; RT_PG_CK_MAGIC(pgp); bu_vls_strcat(str, "polygon solid with no topology (POLY)\n"); sprintf(buf, "\t%ld polygons (faces)\n", (long int)pgp->npoly); bu_vls_strcat(str, buf); sprintf(buf, "\tMost complex face has %lu vertices\n", (long unsigned)pgp->max_npts); bu_vls_strcat(str, buf); if (pgp->npoly) { sprintf(buf, "\tFirst vertex (%g, %g, %g)\n", INTCLAMP(pgp->poly[0].verts[X] * mm2local), INTCLAMP(pgp->poly[0].verts[Y] * mm2local), INTCLAMP(pgp->poly[0].verts[Z] * mm2local)); bu_vls_strcat(str, buf); } if (!verbose) return 0; /* Print out all the vertices of all the faces */ for (i=0; i < pgp->npoly; i++) { fastf_t *v = pgp->poly[i].verts; fastf_t *n = pgp->poly[i].norms; sprintf(buf, "\tPolygon %lu: (%lu pts)\n", (long unsigned)i, (long unsigned)pgp->poly[i].npts); bu_vls_strcat(str, buf); for (j=0; j < pgp->poly[i].npts; j++) { sprintf(buf, "\t\tV (%g, %g, %g)\n\t\t N (%g, %g, %g)\n", INTCLAMP(v[X] * mm2local), INTCLAMP(v[Y] * mm2local), INTCLAMP(v[Z] * mm2local), INTCLAMP(n[X] * mm2local), INTCLAMP(n[Y] * mm2local), INTCLAMP(n[Z] * mm2local)); bu_vls_strcat(str, buf); v += ELEMENTS_PER_VECT; n += ELEMENTS_PER_VECT; } } return 0; }
/** * R T _ P G _ E X P O R T * * The name will be added by the caller. * Generally, only libwdb will set conv2mm != 1.0 */ int rt_pg_export4(struct bu_external *ep, const struct rt_db_internal *ip, double local2mm, const struct db_i *dbip) { struct rt_pg_internal *pgp; union record *rec; size_t i; size_t rno; /* current record number */ size_t p; /* current polygon index */ if (dbip) RT_CK_DBI(dbip); RT_CK_DB_INTERNAL(ip); if (ip->idb_type != ID_POLY) return -1; pgp = (struct rt_pg_internal *)ip->idb_ptr; RT_PG_CK_MAGIC(pgp); BU_CK_EXTERNAL(ep); ep->ext_nbytes = (1 + pgp->npoly) * sizeof(union record); ep->ext_buf = (genptr_t)bu_calloc(1, ep->ext_nbytes, "pg external"); rec = (union record *)ep->ext_buf; rec[0].p.p_id = ID_P_HEAD; for (p=0; p < pgp->npoly; p++) { struct rt_pg_face_internal *pp; rno = p+1; pp = &pgp->poly[p]; if (pp->npts < 3 || pp->npts > 5) { bu_log("rt_pg_export4: unable to support npts=%zu\n", pp->npts); return -1; } rec[rno].q.q_id = ID_P_DATA; rec[rno].q.q_count = pp->npts; for (i=0; i < pp->npts; i++) { /* NOTE: type conversion to dbfloat_t */ VSCALE(rec[rno].q.q_verts[i], &pp->verts[i*3], local2mm); VMOVE(rec[rno].q.q_norms[i], &pp->norms[i*3]); } } bu_log("DEPRECATED: The 'poly' primitive is no longer supported. Use the 'bot' or 'nmg' polygonal mesh instead.\n"); bu_log("\tTo convert polysolids to BOT primitives, use 'dbupgrade'.\n"); 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; }
/** * R T _ P G _ T O _ B O T * * Convert in-memory form of a polysolid (pg) to a bag of triangles (BoT) * There is no record in the V5 database for a polysolid. * * Depends on the "max_npts" parameter having been set. * * Returns - * -1 FAIL * 0 OK */ int rt_pg_to_bot(struct rt_db_internal *ip, const struct bn_tol *tol, struct resource *resp) { struct rt_pg_internal *ip_pg; struct rt_bot_internal *ip_bot; size_t max_pts; size_t max_tri; size_t p; size_t i; RT_CK_DB_INTERNAL(ip); BN_CK_TOL(tol); RT_CK_RESOURCE(resp); if (ip->idb_type != ID_POLY) { bu_log("ERROR: rt_pt_to_bot() called with a non-polysolid!!!\n"); return -1; } ip_pg = (struct rt_pg_internal *)ip->idb_ptr; RT_PG_CK_MAGIC(ip_pg); BU_ALLOC(ip_bot, struct rt_bot_internal); ip_bot->magic = RT_BOT_INTERNAL_MAGIC; ip_bot->mode = RT_BOT_SOLID; ip_bot->orientation = RT_BOT_CCW; ip_bot->bot_flags = 0; /* maximum possible vertices */ max_pts = ip_pg->npoly * ip_pg->max_npts; BU_ASSERT_SIZE_T(max_pts, >, 0); /* maximum possible triangular faces */ max_tri = ip_pg->npoly * 3; BU_ASSERT_SIZE_T(max_tri, >, 0); ip_bot->num_vertices = 0; ip_bot->num_faces = 0; ip_bot->thickness = (fastf_t *)NULL; ip_bot->face_mode = (struct bu_bitv *)NULL; ip_bot->vertices = (fastf_t *)bu_calloc(max_pts * 3, sizeof(fastf_t), "BOT vertices"); ip_bot->faces = (int *)bu_calloc(max_tri * 3, sizeof(int), "BOT faces"); for (p=0; p<ip_pg->npoly; p++) { vect_t work[3], tmp; struct tri_specific trip; fastf_t m1, m2, m3, m4; size_t v0=0, v2=0; int first; first = 1; VMOVE(work[0], &ip_pg->poly[p].verts[0*3]); VMOVE(work[1], &ip_pg->poly[p].verts[1*3]); for (i=2; i < ip_pg->poly[p].npts; i++) { VMOVE(work[2], &ip_pg->poly[p].verts[i*3]); VSUB2(trip.tri_BA, work[1], work[0]); VSUB2(trip.tri_CA, work[2], work[0]); VCROSS(trip.tri_wn, trip.tri_BA, trip.tri_CA); /* Check to see if this plane is a line or pnt */ m1 = MAGNITUDE(trip.tri_BA); m2 = MAGNITUDE(trip.tri_CA); VSUB2(tmp, work[1], work[2]); m3 = MAGNITUDE(tmp); m4 = MAGNITUDE(trip.tri_wn); if (m1 >= tol->dist && m2 >= tol->dist && m3 >= tol->dist && m4 >= tol->dist) { /* add this triangle to the BOT */ if (first) { ip_bot->faces[ip_bot->num_faces * 3] = ip_bot->num_vertices; VMOVE(&ip_bot->vertices[ip_bot->num_vertices * 3], work[0]); v0 = ip_bot->num_vertices; ip_bot->num_vertices++; ip_bot->faces[ip_bot->num_faces * 3 + 1] = ip_bot->num_vertices; VMOVE(&ip_bot->vertices[ip_bot->num_vertices * 3], work[1]); ip_bot->num_vertices++; first = 0; } else { ip_bot->faces[ip_bot->num_faces * 3] = v0; ip_bot->faces[ip_bot->num_faces * 3 + 1] = v2; } VMOVE(&ip_bot->vertices[ip_bot->num_vertices * 3], work[2]); ip_bot->faces[ip_bot->num_faces * 3 + 2] = ip_bot->num_vertices; v2 = ip_bot->num_vertices; ip_bot->num_vertices++; ip_bot->num_faces++; } /* Chop off a triangle, and continue */ VMOVE(work[1], work[2]); } } rt_bot_vertex_fuse(ip_bot, tol); rt_bot_face_fuse(ip_bot); rt_db_free_internal(ip); ip->idb_major_type = DB5_MAJORTYPE_BRLCAD; ip->idb_type = ID_BOT; ip->idb_meth = &rt_functab[ID_BOT]; ip->idb_ptr = ip_bot; return 0; }
/** * R T _ P G _ T E S S */ int rt_pg_tess(struct nmgregion **r, struct model *m, struct rt_db_internal *ip, const struct rt_tess_tol *UNUSED(ttol), const struct bn_tol *tol) { size_t i; struct shell *s; struct vertex **verts; /* dynamic array of pointers */ struct vertex ***vertp;/* dynamic array of ptrs to pointers */ struct faceuse *fu; size_t p; /* current polygon number */ struct rt_pg_internal *pgp; RT_CK_DB_INTERNAL(ip); pgp = (struct rt_pg_internal *)ip->idb_ptr; RT_PG_CK_MAGIC(pgp); *r = nmg_mrsv(m); /* Make region, empty shell, vertex */ s = BU_LIST_FIRST(shell, &(*r)->s_hd); verts = (struct vertex **)bu_malloc( pgp->max_npts * sizeof(struct vertex *), "pg_tess verts[]"); vertp = (struct vertex ***)bu_malloc( pgp->max_npts * sizeof(struct vertex **), "pg_tess vertp[]"); for (i=0; i < pgp->max_npts; i++) vertp[i] = &verts[i]; for (p = 0; p < pgp->npoly; p++) { struct rt_pg_face_internal *pp; pp = &pgp->poly[p]; /* Locate these points, if previously mentioned */ for (i=0; i < pp->npts; i++) { verts[i] = nmg_find_pt_in_shell(s, &pp->verts[3*i], tol); } /* Construct the face. Verts should be in CCW order */ if ((fu = nmg_cmface(s, vertp, pp->npts)) == (struct faceuse *)0) { bu_log("rt_pg_tess() nmg_cmface failed, skipping face %zu\n", p); } /* Associate vertex geometry, where none existed before */ for (i=0; i < pp->npts; i++) { if (verts[i]->vg_p) continue; nmg_vertex_gv(verts[i], &pp->verts[3*i]); } /* Associate face geometry */ if (nmg_calc_face_g(fu)) { nmg_pr_fu_briefly(fu, ""); bu_free((char *)verts, "pg_tess verts[]"); bu_free((char *)vertp, "pg_tess vertp[]"); return -1; /* FAIL */ } } /* Compute "geometry" for region and shell */ nmg_region_a(*r, tol); /* Polysolids are often built with incorrect face normals. * Don't depend on them here. */ nmg_fix_normals(s, tol); bu_free((char *)verts, "pg_tess verts[]"); bu_free((char *)vertp, "pg_tess vertp[]"); return 0; /* OK */ }
/** * 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; }