void nmg_visit_vertex(struct vertex *v, const struct nmg_visit_handlers *htab, void *state) /* Handler's private state */ { NMG_CK_VERTEX(v); if (htab->vis_vertex) htab->vis_vertex((uint32_t *)v, state, 0); if (htab->vis_vertex_g && v->vg_p) htab->vis_vertex_g((uint32_t *)v->vg_p, state, 0); }
static void Write_euclid_face(const struct loopuse *lu, const int facet_type, const int regionid, const int face_number) { struct faceuse *fu; struct edgeuse *eu; plane_t plane; int vertex_count = 0; NMG_CK_LOOPUSE(lu); if (verbose) bu_log("Write_euclid_face: lu=%p, facet_type=%d, regionid=%d, face_number=%d\n", (void *)lu, facet_type, regionid, face_number); if (BU_LIST_FIRST_MAGIC(&lu->down_hd) != NMG_EDGEUSE_MAGIC) return; if (*lu->up.magic_p != NMG_FACEUSE_MAGIC) return; for (BU_LIST_FOR(eu, edgeuse, &lu->down_hd)) vertex_count++; fprintf(fp_out, "%10d%3d 0. 1%5d", regionid, facet_type, vertex_count); vertex_count = 0; for (BU_LIST_FOR(eu, edgeuse, &lu->down_hd)) { struct vertex *v; int i; NMG_CK_EDGEUSE(eu); v = eu->vu_p->v_p; NMG_CK_VERTEX(v); /* fprintf(fp_out, "%10d%8f%8f%8f", ++vertex_count, V3ARGS(v->vg_p->coord)); */ vertex_count++; fprintf(fp_out, "%10d", vertex_count); for (i=X; i<=Z; i++) fastf_print(fp_out, 8, v->vg_p->coord[i]); } fu = lu->up.fu_p; NMG_CK_FACEUSE(fu); NMG_GET_FU_PLANE(plane, fu); fprintf(fp_out, "%10d%15.5f%15.5f%15.5f%15.5f", face_number, V4ARGS(plane)); }
/** * Count number of vertices in an NMG loop. */ static int verts_in_nmg_loop(struct loopuse *lu) { int cnt; struct edgeuse *eu; struct vertex *v; /* Count number of vertices in loop. */ cnt = 0; NMG_CK_LOOPUSE(lu); if (BU_LIST_FIRST_MAGIC(&lu->down_hd) == NMG_EDGEUSE_MAGIC) { for (BU_LIST_FOR(eu, edgeuse, &lu->down_hd)) { NMG_CK_EDGEUSE(eu); NMG_CK_EDGE(eu->e_p); NMG_CK_VERTEXUSE(eu->vu_p); NMG_CK_VERTEX(eu->vu_p->v_p); cnt++; } } else if (BU_LIST_FIRST_MAGIC(&lu->down_hd) == NMG_VERTEXUSE_MAGIC) {
struct iges_vertex * Get_iges_vertex(struct vertex *v) { struct iges_vertex_list *vert_list; NMG_CK_VERTEX(v); vert_list = vertex_root; while (vert_list) { int vert_no; for (vert_no = 0; vert_no < vert_list->no_of_verts; vert_no++) { if (vert_list->i_verts[vert_no].v == v) return &(vert_list->i_verts[vert_no]); } vert_list = vert_list->next; } return (struct iges_vertex *)NULL; }
static void nmg_to_psurf(struct nmgregion *r, FILE *fp_psurf) /* NMG region to be converted. */ /* Jack format file to write vertex list to. */ { int i; int *map; /* map from v->index to Jack vert # */ struct bu_ptbl vtab; /* vertex table */ map = (int *)bu_calloc(r->m_p->maxindex, sizeof(int *), "Jack vert map"); /* Built list of vertex structs */ nmg_vertex_tabulate( &vtab, &r->l.magic ); /* XXX What to do if 0 vertices? */ /* Print list of unique vertices and convert from mm to cm. */ for (i = 0; i < BU_PTBL_END(&vtab); i++) { struct vertex *v; register struct vertex_g *vg; v = (struct vertex *)BU_PTBL_GET(&vtab, i); NMG_CK_VERTEX(v); vg = v->vg_p; NMG_CK_VERTEX_G(vg); NMG_INDEX_ASSIGN( map, v, i+1 ); /* map[v->index] = i+1 */ fprintf(fp_psurf, "%f\t%f\t%f\n", vg->coord[X] / 10., vg->coord[Y] / 10., vg->coord[Z] / 10.); } fprintf(fp_psurf, ";;\n"); jack_faces(r, fp_psurf, map); bu_ptbl( &vtab, BU_PTBL_FREE, 0 ); bu_free( (char *)map, "Jack vert map" ); }
/* * 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; }
/* routine to output the faceted NMG representation of a BRL-CAD region */ static void output_nmg(struct nmgregion *r, const struct db_full_path *pathp, int UNUSED(region_id), int UNUSED(material_id)) { struct model *m; struct shell *s; struct vertex *v; char *region_name; NMG_CK_REGION(r); RT_CK_FULL_PATH(pathp); region_name = db_path_to_string(pathp); m = r->m_p; NMG_CK_MODEL(m); /* triangulate model */ nmg_triangulate_model(m, &tol); /* Output triangles */ if (verbose) { printf("Convert these triangles to your format for region %s\n", region_name); } else { printf("Converted %s\n", region_name); } for (BU_LIST_FOR(s, shell, &r->s_hd)) { struct faceuse *fu; NMG_CK_SHELL(s); for (BU_LIST_FOR(fu, faceuse, &s->fu_hd)) { struct loopuse *lu; /* vect_t facet_normal; */ NMG_CK_FACEUSE(fu); if (fu->orientation != OT_SAME) continue; /* Grab the face normal if needed */ /* NMG_GET_FU_NORMAL(facet_normal, fu); */ for (BU_LIST_FOR(lu, loopuse, &fu->lu_hd)) { struct edgeuse *eu; NMG_CK_LOOPUSE(lu); if (BU_LIST_FIRST_MAGIC(&lu->down_hd) != NMG_EDGEUSE_MAGIC) continue; /* loop through the edges in this loop (facet) */ if (verbose) printf("\tfacet:\n"); for (BU_LIST_FOR(eu, edgeuse, &lu->down_hd)) { NMG_CK_EDGEUSE(eu); v = eu->vu_p->v_p; NMG_CK_VERTEX(v); if (verbose) printf("\t\t(%g %g %g)\n", V3ARGS(v->vg_p->coord)); } tot_polygons++; } } } bu_free(region_name, "region name"); }
void nmg_2_vrml(struct db_tree_state *tsp, const struct db_full_path *pathp, struct model *m) { struct mater_info *mater = &tsp->ts_mater; const struct bn_tol *tol2 = tsp->ts_tol; struct nmgregion *reg; struct bu_ptbl verts; struct vrml_mat mat; struct bu_vls vls = BU_VLS_INIT_ZERO; char *tok; int i; int first = 1; int is_light = 0; point_t ave_pt = VINIT_ZERO; struct bu_vls shape_name = BU_VLS_INIT_ZERO; char *full_path; /* There may be a better way to capture the region_id, than * getting the rt_comb_internal structure, (and may be a better * way to capture the rt_comb_internal struct), but for now I just * copied the method used in select_lights/select_non_lights above, * could have used a global variable but I noticed none other were * used, so I didn't want to be the first */ struct directory *dp; struct rt_db_internal intern; struct rt_comb_internal *comb; int id; /* static due to libbu exception handling */ static float r, g, b; NMG_CK_MODEL(m); full_path = db_path_to_string(pathp); RT_CK_FULL_PATH(pathp); dp = DB_FULL_PATH_CUR_DIR(pathp); if (!(dp->d_flags & RT_DIR_COMB)) { return; } id = rt_db_get_internal(&intern, dp, dbip, (matp_t)NULL, &rt_uniresource); if (id < 0) { bu_log("Cannot internal form of %s\n", dp->d_namep); return; } if (id != ID_COMBINATION) { bu_log("Directory/database mismatch!\n\t is '%s' a combination or not?\n", dp->d_namep); return; } comb = (struct rt_comb_internal *)intern.idb_ptr; RT_CK_COMB(comb); if (mater->ma_color_valid) { r = mater->ma_color[0]; g = mater->ma_color[1]; b = mater->ma_color[2]; } else { r = g = b = 0.5; } if (mater->ma_shader) { tok = strtok(mater->ma_shader, tok_sep); bu_strlcpy(mat.shader, tok, TXT_NAME_SIZE); } else { mat.shader[0] = '\0'; } mat.shininess = -1; mat.transparency = -1.0; mat.lt_fraction = -1.0; VSETALL(mat.lt_dir, 0.0); mat.lt_angle = -1.0; mat.tx_file[0] = '\0'; mat.tx_w = -1; mat.tx_n = -1; bu_vls_strcpy(&vls, &mater->ma_shader[strlen(mat.shader)]); (void)bu_struct_parse(&vls, vrml_mat_parse, (char *)&mat, NULL); if (bu_strncmp("light", mat.shader, 5) == 0) { /* this is a light source */ is_light = 1; } else { path_2_vrml_id(&shape_name, full_path); fprintf(fp_out, "\t\tDEF %s Shape {\n", bu_vls_addr(&shape_name)); fprintf(fp_out, "\t\t\t# Component_ID: %ld %s\n", comb->region_id, full_path); fprintf(fp_out, "\t\t\tappearance Appearance {\n"); if (bu_strncmp("plastic", mat.shader, 7) == 0) { if (mat.shininess < 0) { mat.shininess = 10; } if (mat.transparency < SMALL_FASTF) { mat.transparency = 0.0; } fprintf(fp_out, "\t\t\t\tmaterial Material {\n"); fprintf(fp_out, "\t\t\t\t\tdiffuseColor %g %g %g \n", r, g, b); fprintf(fp_out, "\t\t\t\t\tshininess %g\n", 1.0-exp(-(double)mat.shininess/20.0)); if (mat.transparency > SMALL_FASTF) { fprintf(fp_out, "\t\t\t\t\ttransparency %g\n", mat.transparency); } fprintf(fp_out, "\t\t\t\t\tspecularColor %g %g %g \n\t\t\t\t}\n", 1.0, 1.0, 1.0); } else if (bu_strncmp("glass", mat.shader, 5) == 0) { if (mat.shininess < 0) { mat.shininess = 4; } if (mat.transparency < SMALL_FASTF) { mat.transparency = 0.8; } fprintf(fp_out, "\t\t\t\tmaterial Material {\n"); fprintf(fp_out, "\t\t\t\t\tdiffuseColor %g %g %g \n", r, g, b); fprintf(fp_out, "\t\t\t\t\tshininess %g\n", 1.0-exp(-(double)mat.shininess/20.0)); if (mat.transparency > SMALL_FASTF) { fprintf(fp_out, "\t\t\t\t\ttransparency %g\n", mat.transparency); } fprintf(fp_out, "\t\t\t\t\tspecularColor %g %g %g \n\t\t\t\t}\n", 1.0, 1.0, 1.0); } else if (bu_strncmp("texture", mat.shader, 7) == 0) { if (mat.tx_w < 0) { mat.tx_w = 512; } if (mat.tx_n < 0) { mat.tx_n = 512; } if (strlen(mat.tx_file)) { int tex_fd; unsigned char tex_buf[TXT_BUF_LEN * 3]; if ((tex_fd = open(mat.tx_file, O_RDONLY | O_BINARY)) == (-1)) { bu_log("Cannot open texture file (%s)\n", mat.tx_file); perror("g-vrml: "); } else { long tex_len; long bytes_read = 0; long bytes_to_go = 0; /* Johns note - need to check (test) the texture stuff */ fprintf(fp_out, "\t\t\t\ttextureTransform TextureTransform {\n"); fprintf(fp_out, "\t\t\t\t\tscale 1.33333 1.33333\n\t\t\t\t}\n"); fprintf(fp_out, "\t\t\t\ttexture PixelTexture {\n"); fprintf(fp_out, "\t\t\t\t\trepeatS TRUE\n"); fprintf(fp_out, "\t\t\t\t\trepeatT TRUE\n"); fprintf(fp_out, "\t\t\t\t\timage %d %d %d\n", mat.tx_w, mat.tx_n, 3); tex_len = mat.tx_w*mat.tx_n * 3; while (bytes_read < tex_len) { int nbytes; long readval; bytes_to_go = tex_len - bytes_read; CLAMP(bytes_to_go, 0, TXT_BUF_LEN * 3); nbytes = 0; while (nbytes < bytes_to_go) { readval = read(tex_fd, &tex_buf[nbytes], bytes_to_go-nbytes); if (readval < 0) { perror("READ ERROR"); break; } else { nbytes += readval; } } bytes_read += nbytes; for (i = 0; i < nbytes; i += 3) { fprintf(fp_out, "\t\t\t0x%02x%02x%02x\n", tex_buf[i], tex_buf[i+1], tex_buf[i+2]); } } fprintf(fp_out, "\t\t\t\t}\n"); close(tex_fd); } } } else if (mater->ma_color_valid) { /* no shader specified, but a color is assigned */ fprintf(fp_out, "\t\t\t\tmaterial Material {\n"); fprintf(fp_out, "\t\t\t\t\tdiffuseColor %g %g %g }\n", r, g, b); } else { /* If no color was defined set the colors according to the thousands groups */ int thou = comb->region_id / 1000; thou == 0 ? fprintf(fp_out, "\t\t\tmaterial USE Material_999\n") : thou == 1 ? fprintf(fp_out, "\t\t\tmaterial USE Material_1999\n") : thou == 2 ? fprintf(fp_out, "\t\t\tmaterial USE Material_2999\n") : thou == 3 ? fprintf(fp_out, "\t\t\tmaterial USE Material_3999\n") : thou == 4 ? fprintf(fp_out, "\t\t\tmaterial USE Material_4999\n") : thou == 5 ? fprintf(fp_out, "\t\t\tmaterial USE Material_5999\n") : thou == 6 ? fprintf(fp_out, "\t\t\tmaterial USE Material_6999\n") : thou == 7 ? fprintf(fp_out, "\t\t\tmaterial USE Material_7999\n") : thou == 8 ? fprintf(fp_out, "\t\t\tmaterial USE Material_8999\n") : fprintf(fp_out, "\t\t\tmaterial USE Material_9999\n"); } } if (!is_light) { nmg_triangulate_model(m, tol2); fprintf(fp_out, "\t\t\t}\n"); fprintf(fp_out, "\t\t\tgeometry IndexedFaceSet {\n"); fprintf(fp_out, "\t\t\t\tcoord Coordinate {\n"); } /* get list of vertices */ nmg_vertex_tabulate(&verts, &m->magic); if (!is_light) { fprintf(fp_out, "\t\t\t\t\tpoint ["); } else { VSETALL(ave_pt, 0.0); } for (i = 0; i < BU_PTBL_END(&verts); i++) { struct vertex *v; struct vertex_g *vg; point_t pt_meters; v = (struct vertex *)BU_PTBL_GET(&verts, i); NMG_CK_VERTEX(v); vg = v->vg_p; NMG_CK_VERTEX_G(vg); /* convert to desired units */ VSCALE(pt_meters, vg->coord, scale_factor); if (is_light) { VADD2(ave_pt, ave_pt, pt_meters); } if (first) { if (!is_light) { fprintf(fp_out, " %10.10e %10.10e %10.10e, # point %d\n", V3ARGS(pt_meters), i); } first = 0; } else if (!is_light) { fprintf(fp_out, "\t\t\t\t\t%10.10e %10.10e %10.10e, # point %d\n", V3ARGS(pt_meters), i); } } if (!is_light) { fprintf(fp_out, "\t\t\t\t\t]\n\t\t\t\t}\n"); } else { fastf_t one_over_count; one_over_count = 1.0/(fastf_t)BU_PTBL_END(&verts); VSCALE(ave_pt, ave_pt, one_over_count); } first = 1; if (!is_light) { fprintf(fp_out, "\t\t\t\tcoordIndex [\n"); for (BU_LIST_FOR(reg, nmgregion, &m->r_hd)) { struct shell *s; NMG_CK_REGION(reg); for (BU_LIST_FOR(s, shell, ®->s_hd)) { struct faceuse *fu; NMG_CK_SHELL(s); for (BU_LIST_FOR(fu, faceuse, &s->fu_hd)) { struct loopuse *lu; NMG_CK_FACEUSE(fu); if (fu->orientation != OT_SAME) { continue; } for (BU_LIST_FOR(lu, loopuse, &fu->lu_hd)) { struct edgeuse *eu; NMG_CK_LOOPUSE(lu); if (BU_LIST_FIRST_MAGIC(&lu->down_hd) != NMG_EDGEUSE_MAGIC) { continue; } if (!first) { fprintf(fp_out, ",\n"); } else { first = 0; } fprintf(fp_out, "\t\t\t\t\t"); for (BU_LIST_FOR(eu, edgeuse, &lu->down_hd)) { struct vertex *v; NMG_CK_EDGEUSE(eu); v = eu->vu_p->v_p; NMG_CK_VERTEX(v); fprintf(fp_out, " %d,", bu_ptbl_locate(&verts, (long *)v)); } fprintf(fp_out, "-1"); } } } } fprintf(fp_out, "\n\t\t\t\t]\n\t\t\t\tnormalPerVertex FALSE\n"); fprintf(fp_out, "\t\t\t\tconvex FALSE\n"); fprintf(fp_out, "\t\t\t\tcreaseAngle 0.5\n"); fprintf(fp_out, "\t\t\t}\n\t\t}\n"); } else {
/* * J A C K _ F A C E S * * Continues the conversion of an nmg into Jack format. Before * this routine is called, a list of unique vertices has been * stored in a heap. Using this heap and the nmg structure, a * list of face vertices is written to the Jack data base file. */ static void jack_faces(struct nmgregion *r, FILE *fp_psurf, int *map) /* NMG region to be converted. */ /* Jack format file to write face vertices to. */ { struct edgeuse *eu; struct faceuse *fu; struct loopuse *lu; struct shell *s; struct vertex *v; for (BU_LIST_FOR(s, shell, &r->s_hd)) { /* Shell is made of faces. */ for (BU_LIST_FOR(fu, faceuse, &s->fu_hd)) { NMG_CK_FACEUSE(fu); if (fu->orientation != OT_SAME) continue; for (BU_LIST_FOR(lu, loopuse, &fu->lu_hd)) { NMG_CK_LOOPUSE(lu); if (BU_LIST_FIRST_MAGIC(&lu->down_hd) == NMG_EDGEUSE_MAGIC) { for (BU_LIST_FOR(eu, edgeuse, &lu->down_hd)) { NMG_CK_EDGEUSE(eu); NMG_CK_EDGE(eu->e_p); NMG_CK_VERTEXUSE(eu->vu_p); NMG_CK_VERTEX(eu->vu_p->v_p); NMG_CK_VERTEX_G(eu->vu_p->v_p->vg_p); fprintf(fp_psurf, "%d ", NMG_INDEX_GET(map, eu->vu_p->v_p)); } } else if (BU_LIST_FIRST_MAGIC(&lu->down_hd) == NMG_VERTEXUSE_MAGIC) { v = BU_LIST_PNEXT(vertexuse, &lu->down_hd)->v_p; NMG_CK_VERTEX(v); NMG_CK_VERTEX_G(v->vg_p); fprintf(fp_psurf, "%d ", NMG_INDEX_GET(map, v)); } else bu_log("jack_faces: loopuse mess up! (1)\n"); fprintf(fp_psurf, ";\n"); } } /* Shell contains loops. */ for (BU_LIST_FOR(lu, loopuse, &s->lu_hd)) { NMG_CK_LOOPUSE(lu); if (BU_LIST_FIRST_MAGIC(&lu->down_hd) == NMG_EDGEUSE_MAGIC) { for (BU_LIST_FOR(eu, edgeuse, &lu->down_hd)) { NMG_CK_EDGEUSE(eu); NMG_CK_EDGE(eu->e_p); NMG_CK_VERTEXUSE(eu->vu_p); NMG_CK_VERTEX(eu->vu_p->v_p); NMG_CK_VERTEX_G(eu->vu_p->v_p->vg_p); fprintf(fp_psurf, "%d ", NMG_INDEX_GET(map, eu->vu_p->v_p)); } } else if (BU_LIST_FIRST_MAGIC(&lu->down_hd) == NMG_VERTEXUSE_MAGIC) { v = BU_LIST_PNEXT(vertexuse, &lu->down_hd)->v_p; NMG_CK_VERTEX(v); NMG_CK_VERTEX_G(v->vg_p); fprintf(fp_psurf, "%d ", NMG_INDEX_GET(map, v)); } else bu_log("jack_faces: loopuse mess up! (1)\n"); fprintf(fp_psurf, ";\n"); }
static void nmg_to_obj(struct nmgregion *r, struct db_full_path *pathp, int region_id, int aircode, int los, int material_id) { struct model *m; struct shell *s; struct vertex *v; struct bu_ptbl verts; struct bu_ptbl norms; char *region_name; int numverts = 0; /* Number of vertices to output */ int numtri = 0; /* Number of triangles to output */ int i; NMG_CK_REGION( r ); RT_CK_FULL_PATH(pathp); region_name = db_path_to_string( pathp ); #if 0 printf("Attempting to process region %s\n", region_name); fflush(stdout); #endif m = r->m_p; NMG_CK_MODEL( m ); /* triangulate model */ nmg_triangulate_model( m, &tol ); /* list all vertices in result */ nmg_vertex_tabulate( &verts, &r->l.magic ); /* Get number of vertices */ numverts = BU_PTBL_END (&verts); /* get list of vertexuse normals */ if ( do_normals ) nmg_vertexuse_normal_tabulate( &norms, &r->l.magic ); /* XXX Check vertices, shells faces first? Do not want to punt mid-stream */ /* BEGIN CHECK SECTION */ /* Check vertices */ for ( i=0; i<numverts; i++ ) { v = (struct vertex *)BU_PTBL_GET( &verts, i ); NMG_CK_VERTEX( v ); } /* Check triangles */ for ( BU_LIST_FOR( s, shell, &r->s_hd ) ) { struct faceuse *fu; NMG_CK_SHELL( s ); for ( BU_LIST_FOR( fu, faceuse, &s->fu_hd ) ) { struct loopuse *lu; NMG_CK_FACEUSE( fu ); if ( fu->orientation != OT_SAME ) continue; for ( BU_LIST_FOR( lu, loopuse, &fu->lu_hd ) ) { struct edgeuse *eu; int vert_count=0; NMG_CK_LOOPUSE( lu ); if ( BU_LIST_FIRST_MAGIC( &lu->down_hd ) != NMG_EDGEUSE_MAGIC ) continue; /* check vertex numbers for each triangle */ for ( BU_LIST_FOR( eu, edgeuse, &lu->down_hd ) ) { NMG_CK_EDGEUSE( eu ); v = eu->vu_p->v_p; NMG_CK_VERTEX( v ); vert_count++; i = bu_ptbl_locate( &verts, (long *)v ); if ( i < 0 ) { /*XXX*/ bu_ptbl_free( &verts); /*XXX*/ bu_free( region_name, "region name" ); bu_log( "Vertex from eu x%x is not in nmgregion x%x\n", eu, r ); bu_exit(1, "ERROR: Can't find vertex in list!"); } } if ( vert_count > 3 ) { /*XXX*/ bu_ptbl_free( &verts); /*XXX*/ bu_free( region_name, "region name" ); bu_log( "lu x%x has %d vertices!\n", lu, vert_count ); bu_exit(1, "ERROR: LU is not a triangle\n"); } else if ( vert_count < 3 ) continue; numtri++; } } } /* END CHECK SECTION */ /* Write pertinent info for this region */ if ( usemtl ) fprintf( fp, "usemtl %d_%d_%d\n", aircode, los, material_id ); fprintf( fp, "g %s", pathp->fp_names[0]->d_namep ); for ( i=1; i<pathp->fp_len; i++ ) fprintf( fp, "/%s", pathp->fp_names[i]->d_namep ); fprintf( fp, "\n" ); /* Write vertices */ for ( i=0; i<numverts; i++ ) { v = (struct vertex *)BU_PTBL_GET( &verts, i ); NMG_CK_VERTEX( v ); if (inches) fprintf( fp, "v %f %f %f\n", V3ARGSIN( v->vg_p->coord )); else fprintf( fp, "v %f %f %f\n", V3ARGS( v->vg_p->coord )); } /* Write vertexuse normals */ if ( do_normals ) { for ( i=0; i<BU_PTBL_END( &norms ); i++ ) { struct vertexuse_a_plane *va; va = (struct vertexuse_a_plane *)BU_PTBL_GET( &norms, i ); NMG_CK_VERTEXUSE_A_PLANE( va ); if (inches) fprintf( fp, "vn %f %f %f\n", V3ARGSIN( va->N )); else fprintf( fp, "vn %f %f %f\n", V3ARGS( va->N )); } } /* output triangles */ for ( BU_LIST_FOR( s, shell, &r->s_hd ) ) { struct faceuse *fu; NMG_CK_SHELL( s ); for ( BU_LIST_FOR( fu, faceuse, &s->fu_hd ) ) { struct loopuse *lu; NMG_CK_FACEUSE( fu ); if ( fu->orientation != OT_SAME ) continue; for ( BU_LIST_FOR( lu, loopuse, &fu->lu_hd ) ) { struct edgeuse *eu; int vert_count=0; int use_normals=1; NMG_CK_LOOPUSE( lu ); if ( BU_LIST_FIRST_MAGIC( &lu->down_hd ) != NMG_EDGEUSE_MAGIC ) continue; /* Each vertexuse of the face must have a normal in order * to use the normals in Wavefront */ if ( do_normals ) { for ( BU_LIST_FOR( eu, edgeuse, &lu->down_hd ) ) { NMG_CK_EDGEUSE( eu ); if ( !eu->vu_p->a.magic_p ) { use_normals = 0; break; } if ( *eu->vu_p->a.magic_p != NMG_VERTEXUSE_A_PLANE_MAGIC ) { use_normals = 0; break; } } } else use_normals = 0; fprintf( fp, "f" ); /* list vertex numbers for each triangle */ for ( BU_LIST_FOR( eu, edgeuse, &lu->down_hd ) ) { NMG_CK_EDGEUSE( eu ); v = eu->vu_p->v_p; NMG_CK_VERTEX( v ); vert_count++; i = bu_ptbl_locate( &verts, (long *)v ); if ( i < 0 ) { bu_ptbl_free( &verts); bu_log( "Vertex from eu x%x is not in nmgregion x%x\n", eu, r ); /*XXX*/ bu_free( region_name, "region name" ); /*XXX*/ bu_exit(1, "Can't find vertex in list!\n"); } if ( use_normals ) { int j; j = bu_ptbl_locate( &norms, (long *)eu->vu_p->a.magic_p ); fprintf( fp, " %ld//%ld", i+1+vert_offset, j+1+norm_offset ); } else fprintf( fp, " %ld", i+1+vert_offset ); } fprintf( fp, "\n" ); if ( vert_count > 3 ) { bu_ptbl_free( &verts); bu_free( region_name, "region name" ); bu_log( "lu x%x has %d vertices!\n", lu, vert_count ); bu_exit(1, "ERROR: LU is not a triangle\n" ); } } } }
static void nmg_to_dxf(struct nmgregion *r, const struct db_full_path *pathp, int UNUSED(region_id), int UNUSED(material_id), float color[3]) { struct model *m; struct shell *s; struct vertex *v; struct bu_ptbl verts; char *region_name; int region_polys=0; int tri_count=0; int color_num; int do_triangulate=0; NMG_CK_REGION(r); RT_CK_FULL_PATH(pathp); region_name = db_path_to_string(pathp); m = r->m_p; NMG_CK_MODEL(m); /* Count triangles */ for (BU_LIST_FOR(s, shell, &r->s_hd)) { struct faceuse *fu; NMG_CK_SHELL(s); for (BU_LIST_FOR(fu, faceuse, &s->fu_hd)) { struct loopuse *lu; int vert_count=0; NMG_CK_FACEUSE(fu); if (fu->orientation != OT_SAME) continue; for (BU_LIST_FOR(lu, loopuse, &fu->lu_hd)) { struct edgeuse *eu; if (BU_LIST_FIRST_MAGIC(&lu->down_hd) != NMG_EDGEUSE_MAGIC) continue; for (BU_LIST_FOR(eu, edgeuse, &lu->down_hd)) { vert_count++; } if (vert_count > 3) { do_triangulate = 1; goto triangulate; } tri_count++; } } } triangulate: if (do_triangulate) { /* triangulate model */ nmg_triangulate_model(m, &tol); /* Count triangles */ tri_count = 0; for (BU_LIST_FOR(s, shell, &r->s_hd)) { struct faceuse *fu; for (BU_LIST_FOR(fu, faceuse, &s->fu_hd)) { struct loopuse *lu; if (fu->orientation != OT_SAME) continue; for (BU_LIST_FOR(lu, loopuse, &fu->lu_hd)) { if (BU_LIST_FIRST_MAGIC(&lu->down_hd) != NMG_EDGEUSE_MAGIC) continue; tri_count++; } } } } nmg_vertex_tabulate(&verts, &r->l.magic); color_num = find_closest_color(color); if (polyface_mesh) { size_t i; fprintf(fp, "0\nPOLYLINE\n8\n%s\n62\n%d\n70\n64\n71\n%lu\n72\n%d\n", region_name, color_num, (unsigned long)BU_PTBL_LEN(&verts), tri_count); for (i = 0; i < BU_PTBL_LEN(&verts); i++) { fprintf(fp, "0\nVERTEX\n8\n%s\n", region_name); v = (struct vertex *)BU_PTBL_GET(&verts, i); NMG_CK_VERTEX(v); if (inches) { fprintf(fp, "10\n%f\n20\n%f\n30\n%f\n70\n192\n", V3ARGSIN(v->vg_p->coord)); } else { fprintf(fp, "10\n%f\n20\n%f\n30\n%f\n70\n192\n", V3ARGS(v->vg_p->coord)); } } } /* Check triangles */ for (BU_LIST_FOR(s, shell, &r->s_hd)) { struct faceuse *fu; NMG_CK_SHELL(s); for (BU_LIST_FOR(fu, faceuse, &s->fu_hd)) { struct loopuse *lu; NMG_CK_FACEUSE(fu); if (fu->orientation != OT_SAME) continue; for (BU_LIST_FOR(lu, loopuse, &fu->lu_hd)) { struct edgeuse *eu; int vert_count=0; NMG_CK_LOOPUSE(lu); if (BU_LIST_FIRST_MAGIC(&lu->down_hd) != NMG_EDGEUSE_MAGIC) continue; if (polyface_mesh) { fprintf(fp, "0\nVERTEX\n8\n%s\n70\n128\n10\n0.0\n20\n0.0\n30\n0.0\n", region_name); } else { fprintf(fp, "0\n3DFACE\n8\n%s\n62\n%d\n", region_name, color_num); } /* check vertex numbers for each triangle */ for (BU_LIST_FOR(eu, edgeuse, &lu->down_hd)) { NMG_CK_EDGEUSE(eu); vert_count++; v = eu->vu_p->v_p; NMG_CK_VERTEX(v); if (polyface_mesh) { fprintf(fp, "%d\n%d\n", vert_count+70, bu_ptbl_locate(&verts, (long *)v) + 1); } else { if (inches) { fprintf(fp, "%d\n%f\n%d\n%f\n%d\n%f\n", 10 + vert_count - 1, v->vg_p->coord[X] / 25.4, 20 + vert_count - 1, v->vg_p->coord[Y] / 25.4, 30 + vert_count -1, v->vg_p->coord[Z] / 25.4); } else { fprintf(fp, "%d\n%f\n%d\n%f\n%d\n%f\n", 10 + vert_count - 1, v->vg_p->coord[X], 20 + vert_count - 1, v->vg_p->coord[Y], 30 + vert_count -1, v->vg_p->coord[Z]); } } } if (vert_count > 3) { bu_free(region_name, "region name"); bu_log("lu %p has %d vertices!\n", (void *)lu, vert_count); bu_exit(1, "ERROR: LU is not a triangle\n"); } else if (vert_count < 3) { continue; } else { /* repeat the last vertex for the benefit of codes * that interpret the dxf specification for * 3DFACES as requiring a fourth vertex even when * only three are input. */ if (!polyface_mesh) { vert_count++; if (inches) { fprintf(fp, "%d\n%f\n%d\n%f\n%d\n%f\n", 10 + vert_count - 1, v->vg_p->coord[X] / 25.4, 20 + vert_count - 1, v->vg_p->coord[Y] / 25.4, 30 + vert_count -1, v->vg_p->coord[Z] / 25.4); } else { fprintf(fp, "%d\n%f\n%d\n%f\n%d\n%f\n", 10 + vert_count - 1, v->vg_p->coord[X], 20 + vert_count - 1, v->vg_p->coord[Y], 30 + vert_count -1, v->vg_p->coord[Z]); } } } tot_polygons++; region_polys++; } } } bu_ptbl_free(&verts); bu_free(region_name, "region name"); if (polyface_mesh) { fprintf(fp, "0\nSEQEND\n"); } }
void nmg_2_vrml(FILE *fp, const struct db_full_path *pathp, struct model *m, struct mater_info *mater) { struct nmgregion *reg; struct bu_ptbl verts; struct vrml_mat mat; struct bu_vls vls = BU_VLS_INIT_ZERO; char *tok; int i; int first=1; int is_light=0; float r, g, b; point_t ave_pt; char *full_path; /*There may be a better way to capture the region_id, than getting the rt_comb_internal structure, * (and may be a better way to capture the rt_comb_internal struct), but for now I just copied the * method used in select_lights/select_non_lights above, could have used a global variable but I noticed * none other were used, so I didn't want to be the first */ struct directory *dp; struct rt_db_internal intern; struct rt_comb_internal *comb; int id; NMG_CK_MODEL( m ); BARRIER_CHECK; full_path = db_path_to_string( pathp ); /* replace all occurrences of '.' with '_' */ char_replace(full_path, '.', '_'); RT_CK_FULL_PATH( pathp ); dp = DB_FULL_PATH_CUR_DIR( pathp ); if ( !(dp->d_flags & RT_DIR_COMB) ) return; id = rt_db_get_internal( &intern, dp, dbip, (matp_t)NULL, &rt_uniresource ); if ( id < 0 ) { bu_log( "Cannot internal form of %s\n", dp->d_namep ); return; } if ( id != ID_COMBINATION ) { bu_log( "Directory/database mismatch!\n\t is '%s' a combination or not?\n", dp->d_namep ); return; } comb = (struct rt_comb_internal *)intern.idb_ptr; RT_CK_COMB( comb ); if ( mater->ma_color_valid ) { r = mater->ma_color[0]; g = mater->ma_color[1]; b = mater->ma_color[2]; } else { r = g = b = 0.5; } if ( mater->ma_shader ) { tok = strtok( mater->ma_shader, tok_sep ); bu_strlcpy( mat.shader, tok, TXT_NAME_SIZE ); } else mat.shader[0] = '\0'; mat.shininess = -1; mat.transparency = -1.0; mat.lt_fraction = -1.0; VSETALL( mat.lt_dir, 0.0 ); mat.lt_angle = -1.0; mat.tx_file[0] = '\0'; mat.tx_w = -1; mat.tx_n = -1; bu_vls_strcpy( &vls, &mater->ma_shader[strlen(mat.shader)] ); (void)bu_struct_parse( &vls, vrml_mat_parse, (char *)&mat, NULL); if ( bu_strncmp( "light", mat.shader, 5 ) == 0 ) { /* this is a light source */ is_light = 1; } else { fprintf( fp, "\t<Shape DEF=\"%s\">\n", full_path); fprintf( fp, "\t\t<Appearance>\n"); if ( bu_strncmp( "plastic", mat.shader, 7 ) == 0 ) { if ( mat.shininess < 0 ) mat.shininess = 10; V_MAX(mat.transparency, 0.0); fprintf( fp, "\t\t\t<Material diffuseColor=\"%g %g %g\" shininess=\"%g\" transparency=\"%g\" specularColor=\"%g %g %g\"/>\n", r, g, b, 1.0-exp(-(double)mat.shininess/20.0), mat.transparency, 1.0, 1.0, 1.0); } else if ( bu_strncmp( "glass", mat.shader, 5 ) == 0 ) { if ( mat.shininess < 0 ) mat.shininess = 4; if ( mat.transparency < 0.0 ) mat.transparency = 0.8; fprintf( fp, "\t\t\t<Material diffuseColor=\"%g %g %g\" shininess=\"%g\" transparency=\"%g\" specularColor=\"%g %g %g\"/>\n", r, g, b, 1.0-exp(-(double)mat.shininess/20.0), mat.transparency, 1.0, 1.0, 1.0); } else if ( mater->ma_color_valid ) { fprintf( fp, "\t\t\t<Material diffuseColor=\"%g %g %g\"/>\n", r, g, b); } else { /* If no color was defined set the colors according to the thousands groups */ int thou = comb->region_id/1000; thou == 0 ? fprintf( fp, "\t\t\t<Material USE=\"Material_999\"/>\n") : thou == 1 ? fprintf( fp, "\t\t\t<Material USE=\"Material_1999\"/>\n") : thou == 2 ? fprintf( fp, "\t\t\t<Material USE=\"Material_2999\"/>\n") : thou == 3 ? fprintf( fp, "\t\t\t<Material USE=\"Material_3999\"/>\n") : thou == 4 ? fprintf( fp, "\t\t\t<Material USE=\"Material_4999\"/>\n") : thou == 5 ? fprintf( fp, "\t\t\t<Material USE=\"Material_5999\"/>\n") : thou == 6 ? fprintf( fp, "\t\t\t<Material USE=\"Material_6999\"/>\n") : thou == 7 ? fprintf( fp, "\t\t\t<Material USE=\"Material_7999\"/>\n") : thou == 8 ? fprintf( fp, "\t\t\t<Material USE=\"Material_8999\"/>\n") : fprintf( fp, "\t\t\t<Material USE=\"Material_9999\"/>\n"); } } if ( !is_light ) { process_non_light(m); fprintf( fp, "\t\t</Appearance>\n"); } /* FIXME: need code to handle light */ /* get list of vertices */ nmg_vertex_tabulate( &verts, &m->magic ); fprintf( fp, "\t\t<IndexedFaceSet coordIndex=\"\n"); first = 1; if ( !is_light ) { for ( BU_LIST_FOR( reg, nmgregion, &m->r_hd ) ) { struct shell *s; NMG_CK_REGION( reg ); for ( BU_LIST_FOR( s, shell, ®->s_hd ) ) { struct faceuse *fu; NMG_CK_SHELL( s ); for ( BU_LIST_FOR( fu, faceuse, &s->fu_hd ) ) { struct loopuse *lu; NMG_CK_FACEUSE( fu ); if ( fu->orientation != OT_SAME ) continue; for ( BU_LIST_FOR( lu, loopuse, &fu->lu_hd ) ) { struct edgeuse *eu; NMG_CK_LOOPUSE( lu ); if ( BU_LIST_FIRST_MAGIC( &lu->down_hd ) != NMG_EDGEUSE_MAGIC ) continue; if ( !first ) fprintf( fp, ",\n" ); else first = 0; fprintf( fp, "\t\t\t\t" ); for ( BU_LIST_FOR( eu, edgeuse, &lu->down_hd ) ) { struct vertex *v; NMG_CK_EDGEUSE( eu ); v = eu->vu_p->v_p; NMG_CK_VERTEX( v ); fprintf( fp, " %d,", bu_ptbl_locate( &verts, (long *)v ) ); } fprintf( fp, "-1" ); } } } } /* close coordIndex */ fprintf( fp, "\" "); fprintf( fp, "normalPerVertex=\"false\" "); fprintf( fp, "convex=\"false\" "); fprintf( fp, "creaseAngle=\"0.5\" "); /* close IndexedFaceSet open tag */ fprintf( fp, ">\n"); } fprintf( fp, "\t\t\t<Coordinate point=\""); for ( i=0; i<BU_PTBL_END( &verts ); i++ ) { struct vertex *v; struct vertex_g *vg; point_t pt_meters; v = (struct vertex *)BU_PTBL_GET( &verts, i ); NMG_CK_VERTEX( v ); vg = v->vg_p; NMG_CK_VERTEX_G( vg ); /* convert to desired units */ VSCALE( pt_meters, vg->coord, scale_factor ); if ( is_light ) VADD2( ave_pt, ave_pt, pt_meters ); if ( first ) { if ( !is_light ) fprintf( fp, " %10.10e %10.10e %10.10e, ", V3ARGS(pt_meters)); first = 0; } else if ( !is_light ) fprintf( fp, "%10.10e %10.10e %10.10e, ", V3ARGS( pt_meters )); } /* close point */ fprintf(fp, "\""); /* close Coordinate */ fprintf(fp, "/>\n"); /* IndexedFaceSet end tag */ fprintf( fp, "\t\t</IndexedFaceSet>\n"); /* Shape end tag */ fprintf( fp, "\t</Shape>\n"); BARRIER_CHECK; }
int nmg_class_pt_euvu(const fastf_t *pt, struct edgeuse *eu_in, const struct bn_tol *tol) { struct loopuse *lu; struct edgeuse *prev_eu; struct edgeuse *eu; struct vertex *v0, *v1, *v2; vect_t left; vect_t eu_dir; vect_t other_eudir; vect_t pt_dir; fastf_t xo, yo; fastf_t xpt, ypt; fastf_t len; int quado, quadpt; int nmg_class = NMG_CLASS_Unknown; int eu_is_crack = 0; int prev_eu_is_crack = 0; NMG_CK_EDGEUSE(eu_in); BN_CK_TOL(tol); eu = eu_in; if (UNLIKELY(RTG.NMG_debug & DEBUG_PT_FU)) bu_log("nmg_class_pt_euvu((%g %g %g), eu=%p)\n", V3ARGS(pt), (void *)eu); if (UNLIKELY(*eu->up.magic_p != NMG_LOOPUSE_MAGIC)) { bu_log("nmg_class_pt_euvu() called with eu (%p) that isn't part of a loop\n", (void *)eu); bu_bomb("nmg_class_pt_euvu() called with eu that isn't part of a loop"); } lu = eu->up.lu_p; NMG_CK_LOOPUSE(lu); eu_is_crack = nmg_eu_is_part_of_crack(eu); prev_eu = BU_LIST_PPREV_CIRC(edgeuse, &eu->l); prev_eu_is_crack = nmg_eu_is_part_of_crack(prev_eu); /* if both EU's are cracks, we cannot classify */ if (eu_is_crack && prev_eu_is_crack) return NMG_CLASS_Unknown; if (eu_is_crack) { struct edgeuse *eu_test; int done = 0; if (UNLIKELY(RTG.NMG_debug & DEBUG_PT_FU)) bu_log("nmg_class_pt_euvu: eu %p is a crack\n", (void *)eu); /* find next eu from this vertex that is not a crack */ eu_test = BU_LIST_PNEXT_CIRC(edgeuse, &eu->l); while (!done) { while (eu_test->vu_p->v_p != eu->vu_p->v_p && eu_test != eu) eu_test = BU_LIST_PNEXT_CIRC(edgeuse, &eu_test->l); if (eu_test == eu) done = 1; if (!nmg_eu_is_part_of_crack(eu_test)) done = 1; if (!done) eu_test = BU_LIST_PNEXT_CIRC(edgeuse, &eu_test->l); } if (eu_test == eu) /* can't get away from crack */ return NMG_CLASS_Unknown; else eu = eu_test; if (UNLIKELY(RTG.NMG_debug & DEBUG_PT_FU)) bu_log("\tUsing eu %p instead\n", (void *)eu); } if (prev_eu_is_crack) { struct edgeuse *eu_test; int done = 0; if (UNLIKELY(RTG.NMG_debug & DEBUG_PT_FU)) bu_log("nmg_class_pt_euvu: prev_eu (%p) is a crack\n", (void *)prev_eu); /* find previous eu ending at this vertex that is not a crack */ eu_test = BU_LIST_PPREV_CIRC(edgeuse, &prev_eu->l); while (!done) { while (eu_test->eumate_p->vu_p->v_p != eu->vu_p->v_p && eu_test != prev_eu) eu_test = BU_LIST_PPREV_CIRC(edgeuse, &eu_test->l); if (eu_test == prev_eu) done = 1; if (!nmg_eu_is_part_of_crack(eu_test)) done = 1; if (!done) eu_test = BU_LIST_PPREV_CIRC(edgeuse, &eu_test->l); } if (eu_test == prev_eu) /* can't get away from crack */ return NMG_CLASS_Unknown; else prev_eu = eu_test; if (UNLIKELY(RTG.NMG_debug & DEBUG_PT_FU)) bu_log("\tUsing prev_eu %p instead\n", (void *)prev_eu); } /* left is the Y-axis of our XY-coordinate system */ if (UNLIKELY(nmg_find_eu_leftvec(left, eu))) { bu_log("nmg_class_pt_euvu: nmg_find_eu_leftvec() for eu=%p failed!\n", (void *)eu); bu_bomb("nmg_class_pt_euvu: nmg_find_eu_leftvec() failed!"); } if (UNLIKELY(RTG.NMG_debug & DEBUG_PT_FU)) bu_log("\tprev_eu = %p, left = (%g %g %g)\n", (void *)prev_eu, V3ARGS(left)); /* v0 is the origin of the XY-coordinate system */ v0 = eu->vu_p->v_p; NMG_CK_VERTEX(v0); /* v1 is on the X-axis */ v1 = eu->eumate_p->vu_p->v_p; NMG_CK_VERTEX(v1); /* v2 determines angle prev_eu makes with X-axis */ v2 = prev_eu->vu_p->v_p; NMG_CK_VERTEX(v2); if (UNLIKELY(RTG.NMG_debug & DEBUG_PT_FU)) bu_log("\tv0=%p, v1=%p, v2=%p\n", (void *)v0, (void *)v1, (void *)v2); /* eu_dir is our X-direction */ VSUB2(eu_dir, v1->vg_p->coord, v0->vg_p->coord); /* other_eudir is direction along the previous EU (from origin) */ VSUB2(other_eudir, v2->vg_p->coord, v0->vg_p->coord); if (UNLIKELY(RTG.NMG_debug & DEBUG_PT_FU)) bu_log("\teu_dir=(%g %g %g), other_eudir=(%g %g %g)\n", V3ARGS(eu_dir), V3ARGS(other_eudir)); /* get X and Y components for other_eu */ xo = VDOT(eu_dir, other_eudir); yo = VDOT(left, other_eudir); /* which quadrant does this XY point lie in */ quado = Quadrant(xo, yo); if (UNLIKELY(RTG.NMG_debug & DEBUG_PT_FU)) bu_log("\txo=%g, yo=%g, quadrant=%d\n", xo, yo, quado); /* get direction to PT from origin */ VSUB2(pt_dir, pt, v0->vg_p->coord); if (UNLIKELY(RTG.NMG_debug & DEBUG_PT_FU)) bu_log("\tpt_dir=(%g %g %g)\n", V3ARGS(pt_dir)); /* get X and Y components for PT */ xpt = VDOT(eu_dir, pt_dir); ypt = VDOT(left, pt_dir); /* which quadrant does this XY point lie in */ quadpt = Quadrant(xpt, ypt); if (UNLIKELY(RTG.NMG_debug & DEBUG_PT_FU)) bu_log("\txpt=%g, ypt=%g, quadrant=%d\n", xpt, ypt, quadpt); /* do a quadrant comparison first (cheap!!!) */ if (quadpt < quado) return NMG_CLASS_AinB; if (quadpt > quado) return NMG_CLASS_AoutB; /* both are in the same quadrant, need to normalize the coordinates */ len = sqrt(xo*xo + yo*yo); xo = xo/len; yo = yo/len; len = sqrt(xpt*xpt + ypt*ypt); xpt = xpt/len; ypt = ypt/len; if (UNLIKELY(RTG.NMG_debug & DEBUG_PT_FU)) bu_log("\tNormalized xo, yo=(%g %g), xpt, ypt=(%g %g)\n", xo, yo, xpt, ypt); switch (quadpt) { case 1: if (xpt >= xo && ypt <= yo) nmg_class = NMG_CLASS_AinB; else nmg_class = NMG_CLASS_AoutB; break; case 2: if (xpt >= xo && ypt >= yo) nmg_class = NMG_CLASS_AinB; else nmg_class = NMG_CLASS_AoutB; break; case 3: if (xpt <= xo && ypt >= yo) nmg_class = NMG_CLASS_AinB; else nmg_class = NMG_CLASS_AoutB; break; case 4: if (xpt <= xo && ypt <= yo) nmg_class = NMG_CLASS_AinB; else nmg_class = NMG_CLASS_AoutB; break; default: bu_log("This can't happen (illegal quadrant %d)\n", quadpt); bu_bomb("This can't happen (illegal quadrant)\n"); break; } if (UNLIKELY(RTG.NMG_debug & DEBUG_PT_FU)) bu_log("returning %s\n", nmg_class_name(nmg_class)); return nmg_class; }
static void nmg_to_egg(struct nmgregion *r, const struct db_full_path *pathp, int UNUSED(region_id), int UNUSED(material_id), float UNUSED(color[3]), void *client_data) { struct model *m; struct shell *s; struct vertex *v; char *region_name; int region_polys=0; int vert_count=0; struct egg_conv_data *conv_data = (struct egg_conv_data *)client_data; NMG_CK_REGION(r); RT_CK_FULL_PATH(pathp); region_name = db_path_to_string(pathp); m = r->m_p; NMG_CK_MODEL(m); /* triangulate model */ nmg_triangulate_model(m, &conv_data->tol); /* Write pertinent info for this region */ fprintf(conv_data->fp, " <VertexPool> %s {\n", (region_name+1)); /* Build the VertexPool */ for (BU_LIST_FOR (s, shell, &r->s_hd)) { struct faceuse *fu; NMG_CK_SHELL(s); for (BU_LIST_FOR (fu, faceuse, &s->fu_hd)) { struct loopuse *lu; vect_t facet_normal; NMG_CK_FACEUSE(fu); if (fu->orientation != OT_SAME) continue; /* Grab the face normal and save it for all the vertex loops */ NMG_GET_FU_NORMAL(facet_normal, fu); for (BU_LIST_FOR (lu, loopuse, &fu->lu_hd)) { struct edgeuse *eu; NMG_CK_LOOPUSE(lu); if (BU_LIST_FIRST_MAGIC(&lu->down_hd) != NMG_EDGEUSE_MAGIC) continue; /* check vertex numbers for each triangle */ for (BU_LIST_FOR (eu, edgeuse, &lu->down_hd)) { NMG_CK_EDGEUSE(eu); vert_count++; v = eu->vu_p->v_p; NMG_CK_VERTEX(v); fprintf(conv_data->fp, " <Vertex> %d {\n %f %f %f\n <Normal> { %f %f %f }\n }\n", vert_count, V3ARGS(v->vg_p->coord), V3ARGS(facet_normal)); } } } } fprintf(conv_data->fp, " }\n"); vert_count = 0; for (BU_LIST_FOR (s, shell, &r->s_hd)) { struct faceuse *fu; NMG_CK_SHELL(s); for (BU_LIST_FOR (fu, faceuse, &s->fu_hd)) { struct loopuse *lu; NMG_CK_FACEUSE(fu); if (fu->orientation != OT_SAME) continue; for (BU_LIST_FOR (lu, loopuse, &fu->lu_hd)) { struct edgeuse *eu; NMG_CK_LOOPUSE(lu); if (BU_LIST_FIRST_MAGIC(&lu->down_hd) != NMG_EDGEUSE_MAGIC) continue; fprintf(conv_data->fp, " <Polygon> { \n <RGBA> { 1 1 1 1 } \n <VertexRef> { "); /* check vertex numbers for each triangle */ for (BU_LIST_FOR (eu, edgeuse, &lu->down_hd)) { NMG_CK_EDGEUSE(eu); vert_count++; v = eu->vu_p->v_p; NMG_CK_VERTEX(v); fprintf(conv_data->fp, " %d", vert_count); } fprintf(conv_data->fp, " <Ref> { \"%s\" } }\n }\n", region_name+1); region_polys++; } } } conv_data->tot_polygons += region_polys; bu_free(region_name, "region name"); }
/** * Make a life-and-death decision on every element of a shell. * Descend the "great chain of being" from the face to loop to edge to * vertex, saving or demoting along the way. * * Note that there is no moving of items from one shell to another. */ HIDDEN void nmg_eval_shell(register struct shell *s, struct nmg_bool_state *bs) { struct faceuse *fu; struct faceuse *nextfu; struct loopuse *lu; struct loopuse *nextlu; struct edgeuse *eu; struct edgeuse *nexteu; struct vertexuse *vu; int loops_retained; NMG_CK_SHELL(s); BN_CK_TOL(bs->bs_tol); if (RTG.NMG_debug & DEBUG_VERIFY) nmg_vshell(&s->r_p->s_hd, s->r_p); /* * For each face in the shell, process all the loops in the face, * and then handle the face and all loops as a unit. */ nmg_eval_plot(bs, nmg_eval_count++); /* debug */ fu = BU_LIST_FIRST(faceuse, &s->fu_hd); while (BU_LIST_NOT_HEAD(fu, &s->fu_hd)) { NMG_CK_FACEUSE(fu); nextfu = BU_LIST_PNEXT(faceuse, fu); /* Faceuse mates will be handled at same time as OT_SAME fu */ if (fu->orientation != OT_SAME) { fu = nextfu; continue; } if (fu->fumate_p == nextfu) nextfu = BU_LIST_PNEXT(faceuse, nextfu); /* Consider this face */ NMG_CK_FACE(fu->f_p); loops_retained = 0; lu = BU_LIST_FIRST(loopuse, &fu->lu_hd); while (BU_LIST_NOT_HEAD(lu, &fu->lu_hd)) { NMG_CK_LOOPUSE(lu); nextlu = BU_LIST_PNEXT(loopuse, lu); if (lu->lumate_p == nextlu) nextlu = BU_LIST_PNEXT(loopuse, nextlu); NMG_CK_LOOP(lu->l_p); nmg_ck_lu_orientation(lu, bs->bs_tol); switch (nmg_eval_action(&lu->l_p->magic, bs)) { case BACTION_KILL: /* Kill by demoting loop to edges */ if (BU_LIST_FIRST_MAGIC(&lu->down_hd) == NMG_VERTEXUSE_MAGIC) { /* loop of single vertex */ (void)nmg_klu(lu); } else if (nmg_demote_lu(lu) == 0) { nmg_eval_plot(bs, nmg_eval_count++); /* debug */ } lu = nextlu; continue; case BACTION_RETAIN: loops_retained++; break; default: bu_bomb("nmg_eval_shell() bad BACTION\n"); } lu = nextlu; } if (RTG.NMG_debug & DEBUG_BOOLEVAL) bu_log("faceuse %p loops retained=%d\n", (void *)fu, loops_retained); if (RTG.NMG_debug & DEBUG_VERIFY) nmg_vshell(&s->r_p->s_hd, s->r_p); /* * Here, faceuse will have 0 or more loopuses still in it. * Decide the fate of the face; if the face dies, * then any remaining loops, edges, etc., will die too. */ if (BU_LIST_IS_EMPTY(&fu->lu_hd)) { if (loops_retained) bu_bomb("nmg_eval_shell() empty faceuse with retained loops?\n"); /* faceuse is empty, face & mate die */ if (RTG.NMG_debug & DEBUG_BOOLEVAL) bu_log("faceuse %p empty, kill\n", (void *)fu); nmg_kfu(fu); /* kill face & mate, dequeue from shell */ if (RTG.NMG_debug & DEBUG_VERIFY) nmg_vshell(&s->r_p->s_hd, s->r_p); nmg_eval_plot(bs, nmg_eval_count++); /* debug */ fu = nextfu; continue; } if (loops_retained <= 0) { nmg_pr_fu(fu, (char *)NULL); bu_bomb("nmg_eval_shell() non-empty faceuse, no loops retained?\n"); } fu = nextfu; } if (RTG.NMG_debug & DEBUG_VERIFY) nmg_vshell(&s->r_p->s_hd, s->r_p); /* * For each loop in the shell, process. * Each loop is either a wire-loop, or a vertex-with-self-loop. * Only consider wire loops here. */ nmg_eval_plot(bs, nmg_eval_count++); /* debug */ lu = BU_LIST_FIRST(loopuse, &s->lu_hd); while (BU_LIST_NOT_HEAD(lu, &s->lu_hd)) { NMG_CK_LOOPUSE(lu); nextlu = BU_LIST_PNEXT(loopuse, lu); if (lu->lumate_p == nextlu) nextlu = BU_LIST_PNEXT(loopuse, nextlu); if (BU_LIST_FIRST_MAGIC(&lu->down_hd) == NMG_VERTEXUSE_MAGIC) { /* ignore vertex-with-self-loop */ lu = nextlu; continue; } NMG_CK_LOOP(lu->l_p); switch (nmg_eval_action(&lu->l_p->magic, bs)) { case BACTION_KILL: /* Demote the loopuse into wire edges */ /* kill loop & mate */ if (nmg_demote_lu(lu) == 0) nmg_eval_plot(bs, nmg_eval_count++); /* debug */ lu = nextlu; continue; case BACTION_RETAIN: break; default: bu_bomb("nmg_eval_shell() bad BACTION\n"); } lu = nextlu; } if (RTG.NMG_debug & DEBUG_VERIFY) nmg_vshell(&s->r_p->s_hd, s->r_p); /* * For each wire-edge in the shell, ... */ nmg_eval_plot(bs, nmg_eval_count++); /* debug */ eu = BU_LIST_FIRST(edgeuse, &s->eu_hd); while (BU_LIST_NOT_HEAD(eu, &s->eu_hd)) { NMG_CK_EDGEUSE(eu); nexteu = BU_LIST_PNEXT(edgeuse, eu); /* may be head */ if (eu->eumate_p == nexteu) nexteu = BU_LIST_PNEXT(edgeuse, nexteu); /* Consider this edge */ NMG_CK_EDGE(eu->e_p); switch (nmg_eval_action(&eu->e_p->magic, bs)) { case BACTION_KILL: /* Demote the edegeuse (and mate) into vertices */ if (nmg_demote_eu(eu) == 0) nmg_eval_plot(bs, nmg_eval_count++); /* debug */ eu = nexteu; continue; case BACTION_RETAIN: break; default: bu_bomb("nmg_eval_shell() bad BACTION\n"); } eu = nexteu; } /* * For each lone vertex-with-self-loop, process. * Note that these are intermixed in the loop list. * Each loop is either a wire-loop, or a vertex-with-self-loop. * Only consider cases of vertex-with-self-loop here. * * This case has to be handled separately, because a wire-loop * may be demoted to a set of wire-edges above, some of which * may be retained. The non-retained wire-edges may in turn * be demoted into vertex-with-self-loop objects above, * which will be processed here. */ nmg_eval_plot(bs, nmg_eval_count++); /* debug */ lu = BU_LIST_FIRST(loopuse, &s->lu_hd); while (BU_LIST_NOT_HEAD(lu, &s->lu_hd)) { NMG_CK_LOOPUSE(lu); nextlu = BU_LIST_PNEXT(loopuse, lu); if (BU_LIST_FIRST_MAGIC(&lu->down_hd) != NMG_VERTEXUSE_MAGIC) { /* ignore any remaining wire-loops */ lu = nextlu; continue; } if (nextlu == lu->lumate_p) nextlu = BU_LIST_PNEXT(loopuse, nextlu); vu = BU_LIST_PNEXT(vertexuse, &lu->down_hd); NMG_CK_VERTEXUSE(vu); NMG_CK_VERTEX(vu->v_p); switch (nmg_eval_action(&vu->v_p->magic, bs)) { case BACTION_KILL: /* Eliminate the loopuse, and mate */ nmg_klu(lu); lu = nextlu; continue; case BACTION_RETAIN: break; default: bu_bomb("nmg_eval_shell() bad BACTION\n"); } lu = nextlu; } if (RTG.NMG_debug & DEBUG_VERIFY) nmg_vshell(&s->r_p->s_hd, s->r_p); /* * Final case: shell of a single vertexuse */ vu = s->vu_p; if (vu) { NMG_CK_VERTEXUSE(vu); NMG_CK_VERTEX(vu->v_p); switch (nmg_eval_action(&vu->v_p->magic, bs)) { case BACTION_KILL: nmg_kvu(vu); nmg_eval_plot(bs, nmg_eval_count++); /* debug */ s->vu_p = (struct vertexuse *)0; /* sanity */ break; case BACTION_RETAIN: break; default: bu_bomb("nmg_eval_shell() bad BACTION\n"); } } if (RTG.NMG_debug & DEBUG_VERIFY) nmg_vshell(&s->r_p->s_hd, s->r_p); nmg_eval_plot(bs, nmg_eval_count++); /* debug */ }
struct faceuse * Make_planar_face(struct shell *s, int entityno, int face_orient) { int sol_num; /* IGES solid type number */ int no_of_edges; /* edge count for this loop */ int no_of_param_curves; int vert_count = 0; /* Actual number of vertices used to make face */ struct iges_edge_use *edge_list; /* list of edgeuses from iges loop entity */ struct faceuse *fu = NULL; /* NMG face use */ struct loopuse *lu; /* NMG loop use */ struct vertex ***verts; /* list of vertices */ struct iges_vertex_list *v_list; int done; int i, j, k; /* Acquiring Data */ if (dir[entityno]->param <= pstart) { bu_log("Illegal parameter pointer for entity D%07d (%s)\n" , dir[entityno]->direct, dir[entityno]->name); return 0; } Readrec(dir[entityno]->param); Readint(&sol_num, ""); if (sol_num != 508) { bu_exit(1, "ERROR: Entity #%d is not a loop (it's a %s)\n", entityno, iges_type(sol_num)); } Readint(&no_of_edges, ""); edge_list = (struct iges_edge_use *)bu_calloc(no_of_edges, sizeof(struct iges_edge_use) , "Make_face (edge_list)"); for (i = 0; i < no_of_edges; i++) { Readint(&edge_list[i].edge_is_vertex, ""); Readint(&edge_list[i].edge_de, ""); Readint(&edge_list[i].index, ""); Readint(&edge_list[i].orient, ""); if (!face_orient) { /* need opposite orientation of edge */ if (edge_list[i].orient) edge_list[i].orient = 0; else edge_list[i].orient = 1; } edge_list[i].root = (struct iges_param_curve *)NULL; Readint(&no_of_param_curves, ""); for (j = 0; j < no_of_param_curves; j++) { struct iges_param_curve *new_crv; struct iges_param_curve *crv; Readint(&k, ""); /* ignore iso-parametric flag */ BU_ALLOC(new_crv, struct iges_param_curve); if (edge_list[i].root == (struct iges_param_curve *)NULL) edge_list[i].root = new_crv; else { crv = edge_list[i].root; while (crv->next != (struct iges_param_curve *)NULL) crv = crv->next; crv->next = new_crv; } Readint(&new_crv->curve_de, ""); new_crv->next = (struct iges_param_curve *)NULL; } } verts = (struct vertex ***)bu_calloc(no_of_edges, sizeof(struct vertex **) , "Make_face: vertex_list **"); for (i = 0; i < no_of_edges; i++) { if (face_orient) verts[i] = Get_vertex(&edge_list[i]); else verts[no_of_edges-1-i] = Get_vertex(&edge_list[i]); } /* eliminate zero length edges */ vert_count = no_of_edges; done = 0; while (!done) { done = 1; for (i = 0; i < vert_count; i++) { k = i + 1; if (k == vert_count) k = 0; if (verts[i] == verts[k]) { bu_log("Ignoring zero length edge\n"); done = 0; vert_count--; for (j = i; j < vert_count; j++) verts[j] = verts[j+1]; } } } if (vert_count) { plane_t pl; /* Plane equation for face */ fastf_t area; /* area of loop */ fastf_t dist; vect_t min2max; point_t outside_pt; fu = nmg_cmface(s, verts, vert_count); /* associate geometry */ v_list = vertex_root; while (v_list != NULL) { for (i = 0; i < v_list->no_of_verts; i++) { if (v_list->i_verts[i].v != NULL && v_list->i_verts[i].v->vg_p == NULL) { NMG_CK_VERTEX(v_list->i_verts[i].v); nmg_vertex_gv(v_list->i_verts[i].v , v_list->i_verts[i].pt); } } v_list = v_list->next; } lu = BU_LIST_FIRST(loopuse, &fu->lu_hd); NMG_CK_LOOPUSE(lu); area = nmg_loop_plane_area(lu, pl); if (area < 0.0) { bu_log("Could not calculate area for face (entityno = %d)\n", entityno); nmg_pr_fu_briefly(fu, ""); nmg_kfu(fu); fu = (struct faceuse *)NULL; goto err; } nmg_face_g(fu, pl); nmg_face_bb(fu->f_p, &tol); /* find a point that is surely outside the loop */ VSUB2(min2max, fu->f_p->max_pt, fu->f_p->min_pt); VADD2(outside_pt, fu->f_p->max_pt, min2max); /* move it to the plane of the face */ dist = DIST_PT_PLANE(outside_pt, pl); VJOIN1(outside_pt, outside_pt, -dist, pl); if (nmg_class_pt_lu_except(outside_pt, lu, (struct edge *)NULL, &tol) != NMG_CLASS_AoutB) { nmg_reverse_face(fu); if (fu->orientation != OT_SAME) { fu = fu->fumate_p; if (fu->orientation != OT_SAME) bu_exit(1, "ERROR: no OT_SAME use for a face!\n"); } } } else bu_log("No edges left!\n"); err: bu_free((char *)edge_list, "Make_face (edge_list)"); bu_free((char *)verts, "Make_face (vertexlist)"); return fu; }
static void nmg_to_acad(struct nmgregion *r, const struct db_full_path *pathp, int region_id) { struct model *m; struct shell *s; struct vertex *v; struct bu_ptbl verts; char *region_name; int numverts = 0; /* Number of vertices to output */ int numtri = 0; /* Number of triangles to output */ int tricount = 0; /* Triangle number */ int i; NMG_CK_REGION(r); RT_CK_FULL_PATH(pathp); region_name = db_path_to_string(pathp); m = r->m_p; NMG_CK_MODEL(m); /* triangulate model */ nmg_triangulate_model(m, &tol); /* list all vertices in result */ nmg_vertex_tabulate(&verts, &r->l.magic); /* Get number of vertices */ numverts = BU_PTBL_END (&verts); /* BEGIN CHECK SECTION */ /* Check vertices */ for (i=0; i<numverts; i++) { v = (struct vertex *)BU_PTBL_GET(&verts, i); NMG_CK_VERTEX(v); } /* Check triangles */ for (BU_LIST_FOR(s, shell, &r->s_hd)) { struct faceuse *fu; NMG_CK_SHELL(s); for (BU_LIST_FOR(fu, faceuse, &s->fu_hd)) { struct loopuse *lu; NMG_CK_FACEUSE(fu); if (fu->orientation != OT_SAME) continue; for (BU_LIST_FOR(lu, loopuse, &fu->lu_hd)) { struct edgeuse *eu; int vert_count=0; NMG_CK_LOOPUSE(lu); if (BU_LIST_FIRST_MAGIC(&lu->down_hd) != NMG_EDGEUSE_MAGIC) continue; /* check vertex numbers for each triangle */ for (BU_LIST_FOR(eu, edgeuse, &lu->down_hd)) { NMG_CK_EDGEUSE(eu); v = eu->vu_p->v_p; NMG_CK_VERTEX(v); vert_count++; i = bu_ptbl_locate(&verts, (long *)v); if (i < 0) { bu_ptbl_free(&verts); bu_free(region_name, "region name"); bu_log("Vertex from eu %p is not in nmgregion %p\n", (void *)eu, (void *)r); bu_exit(1, "ERROR: Triangle vertex was not located\n"); } } if (vert_count > 3) { bu_ptbl_free(&verts); bu_free(region_name, "region name"); bu_log("lu %p has too many (%d) vertices!\n", (void *)lu, vert_count); bu_exit(1, "ERROR: LU is not a triangle\n"); } else if (vert_count < 3) continue; numtri++; } } } /* END CHECK SECTION */ /* Write pertinent info for this region */ fprintf(fp, "%s\n", (region_name+1)); /* No mirror plane */ fprintf(fp, "%d\n", 0); /* Number of vertices */ fprintf(fp, "%d\n", numverts); /* Write numverts, then vertices */ for (i=0; i<numverts; i++) { v = (struct vertex *)BU_PTBL_GET(&verts, i); NMG_CK_VERTEX(v); if (inches) fprintf(fp, "%f %f %f\n", V3ARGSIN(v->vg_p->coord)); else fprintf(fp, "%f %f %f\n", V3ARGS(v->vg_p->coord)); } /* Number of sub-parts (always 1 with BRL-CAD) */ fprintf(fp, "%d\n", 1); /* Write out name again */ fprintf(fp, "%s\n", (region_name+1)); /* Number of triangles, number of vert/tri (3) */ fprintf(fp, "%d %d\n", numtri, 3); /* output triangles */ for (BU_LIST_FOR(s, shell, &r->s_hd)) { struct faceuse *fu; NMG_CK_SHELL(s); for (BU_LIST_FOR(fu, faceuse, &s->fu_hd)) { struct loopuse *lu; NMG_CK_FACEUSE(fu); if (fu->orientation != OT_SAME) continue; for (BU_LIST_FOR(lu, loopuse, &fu->lu_hd)) { struct edgeuse *eu; int vert_count=0; NMG_CK_LOOPUSE(lu); if (BU_LIST_FIRST_MAGIC(&lu->down_hd) != NMG_EDGEUSE_MAGIC) continue; /* list vertex numbers for each triangle */ for (BU_LIST_FOR(eu, edgeuse, &lu->down_hd)) { NMG_CK_EDGEUSE(eu); v = eu->vu_p->v_p; NMG_CK_VERTEX(v); vert_count++; i = bu_ptbl_locate(&verts, (long *)v); if (i < 0) { bu_ptbl_free(&verts); bu_log("Vertex from eu %p is not in nmgregion %p\n", (void *)eu, (void *)r); bu_free(region_name, "region name"); bu_exit(1, "ERROR: Can't find vertex in list!\n"); } fprintf(fp, " %d", i+1); } /* Output other info. for triangle ICOAT, component#, facet# */ /* Map Icoat from material table later */ /* fprintf(fp, "%s icomp=%d material=%d:\n", (region_name+1), region_id);*/ fprintf(fp, " %d %d %d\n", 0, region_id, ++tricount); if (vert_count > 3) { bu_ptbl_free(&verts); bu_free(region_name, "region name"); bu_log("lu %p has %d vertices!\n", (void *)lu, vert_count); bu_exit(1, "ERROR: LU is not a triangle\n"); } else if (vert_count < 3) continue; tot_polygons++; } } } /* regions_converted++; printf("Processed region %s\n", region_name); printf("Regions attempted = %d Regions done = %d\n", regions_tried, regions_converted); fflush(stdout); */ bu_ptbl_free(&verts); bu_free(region_name, "region name"); }