HIDDEN void cho_deleteProc(ClientData clientData) { struct bu_cmdhist_obj *chop = (struct bu_cmdhist_obj *)clientData; struct bu_cmdhist *curr, *next; /* free list of commands */ curr = BU_LIST_NEXT(bu_cmdhist, &chop->cho_head.l); while (BU_LIST_NOT_HEAD(curr, &chop->cho_head.l)) { curr = BU_LIST_NEXT(bu_cmdhist, &chop->cho_head.l); next = BU_LIST_PNEXT(bu_cmdhist, curr); bu_vls_free(&curr->h_command); BU_LIST_DEQUEUE(&curr->l); bu_free((genptr_t)curr, "cho_deleteProc: curr"); curr = next; } bu_vls_free(&chop->cho_name); bu_vls_free(&chop->cho_head.h_command); BU_LIST_DEQUEUE(&chop->l); BU_PUT(chop, struct bu_cmdhist_obj); }
/* * Illuminate/highlight database object * * Usage: * illum [-n] obj * */ int ged_illum(struct ged *gedp, int argc, const char *argv[]) { struct display_list *gdlp; struct display_list *next_gdlp; int found = 0; int illum = 1; static const char *usage = "[-n] obj"; GED_CHECK_DATABASE_OPEN(gedp, GED_ERROR); GED_CHECK_DRAWABLE(gedp, GED_ERROR); GED_CHECK_ARGC_GT_0(gedp, argc, GED_ERROR); /* initialize result */ bu_vls_trunc(gedp->ged_result_str, 0); /* must be wanting help */ if (argc == 1) { bu_vls_printf(gedp->ged_result_str, "Usage: %s %s", argv[0], usage); return GED_HELP; } if (argc == 3) { if (argv[1][0] == '-' && argv[1][1] == 'n') illum = 0; else goto bad; --argc; ++argv; } if (argc != 2) goto bad; gdlp = BU_LIST_NEXT(display_list, gedp->ged_gdp->gd_headDisplay); while (BU_LIST_NOT_HEAD(gdlp, gedp->ged_gdp->gd_headDisplay)) { next_gdlp = BU_LIST_PNEXT(display_list, gdlp); found += dl_set_illum(gdlp, argv[1], illum); gdlp = next_gdlp; } if (!found) { bu_vls_printf(gedp->ged_result_str, "illum: %s not found", argv[1]); return GED_ERROR; } return GED_OK; bad: bu_vls_printf(gedp->ged_result_str, "Usage: %s %s", argv[0], usage); return GED_ERROR; }
/* * Usage: * write i|next c x y z */ static int vdraw_write_tcl(void *clientData, int argc, const char *argv[]) { struct dg_obj *dgop = (struct dg_obj *)clientData; size_t idx; unsigned long uind = 0; struct bn_vlist *vp, *cp; if (!dgop->dgo_currVHead) { Tcl_AppendResult(dgop->interp, "vdraw write: no vlist is currently open.", (char *)NULL); return TCL_ERROR; } if (argc < 4) { Tcl_AppendResult(dgop->interp, "vdraw write: not enough args\n", (char *)NULL); return TCL_ERROR; } if (argv[1][0] == 'n') { /* next */ for (REV_BU_LIST_FOR(vp, bn_vlist, &(dgop->dgo_currVHead->vdc_vhd))) { if (vp->nused > 0) { break; } } if (BU_LIST_IS_HEAD(vp, &(dgop->dgo_currVHead->vdc_vhd))) { /* we went all the way through */ vp = BU_LIST_PNEXT(bn_vlist, vp); if (BU_LIST_IS_HEAD(vp, &(dgop->dgo_currVHead->vdc_vhd))) { RT_GET_VLIST(vp); BU_LIST_INSERT(&(dgop->dgo_currVHead->vdc_vhd), &(vp->l)); } } if (vp->nused >= BN_VLIST_CHUNK) { vp = BU_LIST_PNEXT(bn_vlist, vp); if (BU_LIST_IS_HEAD(vp, &(dgop->dgo_currVHead->vdc_vhd))) { RT_GET_VLIST(vp); BU_LIST_INSERT(&(dgop->dgo_currVHead->vdc_vhd), &(vp->l)); } } cp = vp; idx = vp->nused; } else if (sscanf(argv[1], "%lu", &uind) < 1) {
void nurb_c_to_bezier(struct bu_list *clist, struct edge_g_cnurb *crv) { fastf_t knot_min, knot_max; int i; struct edge_g_cnurb *crv1, *crv_copy; int done; /* make a copy of original curve */ crv_copy = rt_nurb_crv_copy( crv ); /* split curve at each knot value */ done = 0; while ( !done ) { fastf_t split; knot_min = crv_copy->k.knots[0]; knot_max = crv_copy->k.knots[crv_copy->k.k_size-1]; split = MAX_FASTF; for ( i=1; i<crv_copy->k.k_size-1; i++ ) { if ( crv_copy->k.knots[i] != knot_min && crv_copy->k.knots[i] != knot_max ) { split = crv_copy->k.knots[i]; break; } } if ( split == MAX_FASTF ) { done = 1; BU_LIST_APPEND( clist, &crv_copy->l ); break; } crv1 = rt_nurb_c_xsplit( crv_copy, split ); rt_nurb_free_cnurb( crv_copy ); crv_copy = BU_LIST_PNEXT( edge_g_cnurb, &crv1->l ); BU_LIST_DEQUEUE( &crv_copy->l ); BU_LIST_APPEND( clist, &crv1->l ); } }
int bu_cmdhist_next(void *clientData, int argc, const char **UNUSED(argv)) { struct bu_cmdhist_obj *chop = (struct bu_cmdhist_obj *)clientData; if (argc != 2) { bu_log("ERROR: expecting only two arguments\n"); return BRLCAD_ERROR; } if (BU_LIST_IS_HEAD(chop->cho_curr, &chop->cho_head.l)) return BRLCAD_ERROR; chop->cho_curr = BU_LIST_PNEXT(bu_cmdhist, chop->cho_curr); if (BU_LIST_IS_HEAD(chop->cho_curr, &chop->cho_head.l)) return BRLCAD_ERROR; /* result is in chop->cho_curr */ return BRLCAD_OK; }
/* * 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"); }
int ged_saveview(struct ged *gedp, int argc, const char *argv[]) { struct ged_display_list *gdlp; struct ged_display_list *next_gdlp; int i; FILE *fp; char *base; int c; char rtcmd[255] = {'r', 't', 0}; char outlog[255] = {0}; char outpix[255] = {0}; char inputg[255] = {0}; static const char *usage = "[-e] [-i] [-l] [-o] filename [args]"; GED_CHECK_DATABASE_OPEN(gedp, GED_ERROR); GED_CHECK_VIEW(gedp, GED_ERROR); GED_CHECK_ARGC_GT_0(gedp, argc, GED_ERROR); /* initialize result */ bu_vls_trunc(gedp->ged_result_str, 0); /* must be wanting help */ if (argc == 1) { bu_vls_printf(gedp->ged_result_str, "Usage: %s %s", argv[0], usage); return GED_HELP; } bu_optind = 1; while ((c = bu_getopt(argc, (char * const *)argv, "e:i:l:o:")) != -1) { switch (c) { case 'e': snprintf(rtcmd, 255, "%s", bu_optarg); break; case 'l': snprintf(outlog, 255, "%s", bu_optarg); break; case 'o': snprintf(outpix, 255, "%s", bu_optarg); break; case 'i': snprintf(inputg, 255, "%s", bu_optarg); break; default: { bu_vls_printf(gedp->ged_result_str, "Option '%c' unknown\n", c); bu_vls_printf(gedp->ged_result_str, "help saveview"); return GED_ERROR; } } } argc -= bu_optind-1; argv += bu_optind-1; if (argc < 2) { bu_vls_printf(gedp->ged_result_str, "Usage: %s %s", argv[0], usage); return GED_ERROR; } if ((fp = fopen(argv[1], "a")) == NULL) { perror(argv[1]); return GED_ERROR; } (void)bu_fchmod(fileno(fp), 0755); /* executable */ if (!gedp->ged_wdbp->dbip->dbi_filename) { bu_log("Error: geometry file is not specified\n"); fclose(fp); return GED_ERROR; } if (!bu_file_exists(gedp->ged_wdbp->dbip->dbi_filename, NULL)) { bu_log("Error: %s does not exist\n", gedp->ged_wdbp->dbip->dbi_filename); fclose(fp); return GED_ERROR; } base = basename_without_suffix(argv[1], ".sh"); if (outpix[0] == '\0') { snprintf(outpix, 255, "%s.pix", base); } if (outlog[0] == '\0') { snprintf(outlog, 255, "%s.log", base); } /* Do not specify -v option to rt; batch jobs must print everything. -Mike */ fprintf(fp, "#!/bin/sh\n%s -M ", rtcmd); if (gedp->ged_gvp->gv_perspective > 0) fprintf(fp, "-p%g ", gedp->ged_gvp->gv_perspective); for (i = 2; i < argc; i++) fprintf(fp, "%s ", argv[i]); if (bu_strncmp(rtcmd, "nirt", 4) != 0) fprintf(fp, "\\\n -o %s\\\n $*\\\n", outpix); if (inputg[0] == '\0') { snprintf(inputg, 255, "%s", gedp->ged_wdbp->dbip->dbi_filename); } fprintf(fp, " '%s'\\\n ", inputg); gdlp = BU_LIST_NEXT(ged_display_list, gedp->ged_gdp->gd_headDisplay); while (BU_LIST_NOT_HEAD(gdlp, gedp->ged_gdp->gd_headDisplay)) { next_gdlp = BU_LIST_PNEXT(ged_display_list, gdlp); fprintf(fp, "'%s' ", bu_vls_addr(&gdlp->gdl_path)); gdlp = next_gdlp; } fprintf(fp, "\\\n 2>> %s\\\n", outlog); fprintf(fp, " <<EOF\n"); { vect_t eye_model; _ged_rt_set_eye_model(gedp, eye_model); _ged_rt_write(gedp, fp, eye_model); } fprintf(fp, "\nEOF\n"); (void)fclose(fp); return GED_OK; }
/** * Make a list of all edgeuses which are at the same distance as the * first element on the list. Toss out opposing pairs of edgeuses of the * same edge. * */ HIDDEN void make_near_list(struct edge_info *edge_list, struct bu_list *near1, const struct bn_tol *tol) { struct edge_info *ei; struct edge_info *ei_p; struct edge_info *tmp; fastf_t dist; BU_CK_LIST_HEAD(&edge_list->l); BU_CK_LIST_HEAD(near1); /* toss opposing pairs of uses of the same edge from the list */ ei = BU_LIST_FIRST(edge_info, &edge_list->l); while (BU_LIST_NOT_HEAD(&ei->l, &edge_list->l)) { NMG_CK_EI(ei); ei_p = BU_LIST_FIRST(edge_info, &edge_list->l); while (BU_LIST_NOT_HEAD(&ei_p->l, &edge_list->l)) { NMG_CK_EI(ei_p); NMG_CK_VED(ei_p->ved_p); /* if we've found an opposing use of the same * edge toss the pair of them */ if (ei_p->ved_p->magic_p == ei->ved_p->magic_p && ei_p->eu_p->eumate_p->vu_p->v_p == ei->eu_p->vu_p->v_p && ei_p->eu_p->vu_p->v_p == ei->eu_p->eumate_p->vu_p->v_p) { if (UNLIKELY(RTG.NMG_debug & DEBUG_PT_FU)) { bu_log("tossing edgeuse pair:\n"); bu_log("(%g %g %g) -> (%g %g %g)\n", V3ARGS(ei->eu_p->vu_p->v_p->vg_p->coord), V3ARGS(ei->eu_p->eumate_p->vu_p->v_p->vg_p->coord)); bu_log("(%g %g %g) -> (%g %g %g)\n", V3ARGS(ei_p->eu_p->vu_p->v_p->vg_p->coord), V3ARGS(ei_p->eu_p->eumate_p->vu_p->v_p->vg_p->coord)); } tmp = ei_p; ei_p = BU_LIST_PLAST(edge_info, &ei_p->l); BU_LIST_DEQUEUE(&tmp->l); bu_free((char *)tmp, "edge info struct"); tmp = ei; ei = BU_LIST_PLAST(edge_info, &ei->l); BU_LIST_DEQUEUE(&tmp->l); bu_free((char *)tmp, "edge info struct"); break; } ei_p = BU_LIST_PNEXT(edge_info, &ei_p->l); } ei = BU_LIST_PNEXT(edge_info, &ei->l); } if (BU_LIST_IS_EMPTY(&edge_list->l)) return; ei = BU_LIST_FIRST(edge_info, &edge_list->l); NMG_CK_EI(ei); NMG_CK_VED(ei->ved_p); dist = ei->ved_p->dist; /* create "near" list with all ei's at this dist */ for (BU_LIST_FOR(ei, edge_info, &edge_list->l)) { NMG_CK_EI(ei); NMG_CK_VED(ei->ved_p); if (NEAR_EQUAL(ei->ved_p->dist, dist, tol->dist_sq)) { ei_p = BU_LIST_PLAST(edge_info, &ei->l); BU_LIST_DEQUEUE(&ei->l); BU_LIST_APPEND(near1, &ei->l); ei = ei_p; } } if (UNLIKELY(RTG.NMG_debug & DEBUG_PT_FU)) { bu_log("dist %g near list\n", dist); for (BU_LIST_FOR(ei, edge_info, near1)) { bu_log("\t(%g %g %g) -> (%g %g %g)\n", V3ARGS(ei->eu_p->vu_p->v_p->vg_p->coord), V3ARGS(ei->eu_p->eumate_p->vu_p->v_p->vg_p->coord)); bu_log("\tdist:%g class:%s status:%d\n\t\tv1(%g %g %g) v2(%g %g %g)\n", ei->ved_p->dist, nmg_class_name(ei->nmg_class), ei->ved_p->status, V3ARGS(ei->ved_p->v1->vg_p->coord), V3ARGS(ei->ved_p->v2->vg_p->coord)); bu_log("\tei->ved_p->magic_p=%p, ei->eu_p->vu_p=%p, ei->eu_p->eumate_p->vu_p=%p\n", (void *)ei->ved_p->magic_p, (void *)ei->eu_p->vu_p, (void *)ei->eu_p->eumate_p->vu_p); } }
union tree * nmg_region_end(struct db_tree_state *tsp, const struct db_full_path *pathp, union tree *curtree, void *UNUSED(client_data)) { struct nmgregion *r; struct bu_list vhead; union tree *ret_tree; char *name; RT_CK_TESS_TOL(tsp->ts_ttol); BN_CK_TOL(tsp->ts_tol); NMG_CK_MODEL(*tsp->ts_m); BARRIER_CHECK; BU_LIST_INIT(&vhead); if (RT_G_DEBUG&DEBUG_TREEWALK || verbose) { bu_log("\nConverted %d%% so far (%d of %d)\n", regions_tried>0 ? (regions_converted * 100) / regions_tried : 0, regions_converted, regions_tried ); } if (curtree->tr_op == OP_NOP) return curtree; name = db_path_to_string( pathp ); bu_log( "Attempting %s\n", name ); regions_tried++; ret_tree = process_boolean(curtree, tsp, pathp); if ( ret_tree ) r = ret_tree->tr_d.td_r; else r = (struct nmgregion *)NULL; bu_free( name, "db_path_to_string" ); regions_converted++; if (r != (struct nmgregion *)NULL) { struct shell *s; int empty_region=0; int empty_model=0; /* Kill cracks */ s = BU_LIST_FIRST( shell, &r->s_hd ); while ( BU_LIST_NOT_HEAD( &s->l, &r->s_hd ) ) { struct shell *next_s; next_s = BU_LIST_PNEXT( shell, &s->l ); if ( nmg_kill_cracks( s ) ) { if ( nmg_ks( s ) ) { empty_region = 1; break; } } s = next_s; } /* kill zero length edgeuses */ if ( !empty_region ) { empty_model = nmg_kill_zero_length_edgeuses( *tsp->ts_m ); } if ( !empty_region && !empty_model ) { /* Write the nmgregion to the output file */ nmg_2_vrml( outfp, pathp, r->m_p, &tsp->ts_mater ); } /* NMG region is no longer necessary */ if ( !empty_model ) nmg_kr(r); } else bu_log( "WARNING: Nothing left after Boolean evaluation of %s\n", db_path_to_string( pathp ) ); /* * Dispose of original tree, so that all associated dynamic * memory is released now, not at the end of all regions. * A return of TREE_NULL from this routine signals an error, * so we need to cons up an OP_NOP node to return. */ db_free_tree(curtree, &rt_uniresource); /* Does an nmg_kr() */ BU_ALLOC(curtree, union tree); RT_TREE_INIT(curtree); curtree->tr_op = OP_NOP; BARRIER_CHECK; return curtree; }
/* * Called from db_walk_tree(). * * This routine must be prepared to run in parallel. */ union tree * do_region_end(struct db_tree_state *tsp, const struct db_full_path *pathp, union tree *curtree, void *UNUSED(client_data)) { struct nmgregion *r; struct bu_list vhead; union tree *ret_tree; if (verbose) bu_log("do_region_end: regionid = %d\n", tsp->ts_regionid); RT_CK_TESS_TOL(tsp->ts_ttol); BN_CK_TOL(tsp->ts_tol); NMG_CK_MODEL(*tsp->ts_m); BU_LIST_INIT(&vhead); if (RT_G_DEBUG&DEBUG_TREEWALK || verbose) { char *sofar = db_path_to_string(pathp); bu_log("\ndo_region_end(%d %d%%) %s\n", regions_tried, regions_tried>0 ? (regions_converted * 100) / regions_tried : 0, sofar); bu_free(sofar, "path string"); } if (curtree->tr_op == OP_NOP) return curtree; regions_tried++; if (verbose) bu_log("\tEvaluating region\n"); ret_tree = process_boolean(curtree, tsp, pathp); if (ret_tree) r = ret_tree->tr_d.td_r; else r = (struct nmgregion *)NULL; regions_converted++; if (r != (struct nmgregion *)NULL) { struct shell *s; int empty_region = 0; int empty_model = 0; /* Kill cracks */ s = BU_LIST_FIRST(shell, &r->s_hd); while (BU_LIST_NOT_HEAD(&s->l, &r->s_hd)) { struct shell *next_s; next_s = BU_LIST_PNEXT(shell, &s->l); if (nmg_kill_cracks(s)) { if (nmg_ks(s)) { empty_region = 1; break; } } s = next_s; } /* kill zero length edgeuses */ if (!empty_region) { empty_model = nmg_kill_zero_length_edgeuses(*tsp->ts_m); } if (!empty_region && !empty_model) { /* Write the region to the EUCLID file */ Write_euclid_region(r, tsp); } if (!empty_model) nmg_kr(r); } /* * Dispose of original tree, so that all associated dynamic * memory is released now, not at the end of all regions. * A return of TREE_NULL from this routine signals an error, * so we need to cons up an OP_NOP node to return. */ db_free_tree(curtree, &rt_uniresource); /* Does an nmg_kr() */ BU_ALLOC(curtree, union tree); RT_TREE_INIT(curtree); curtree->tr_op = OP_NOP; return curtree; }
union tree * gcv_region_end_mc(struct db_tree_state *tsp, const struct db_full_path *pathp, union tree *curtree, void *client_data) { union tree *tp = NULL; struct model *m = NULL; struct nmgregion *r = NULL; struct shell *s = NULL; struct bu_list vhead; int empty_region = 0; int empty_model = 0; int NMG_debug_state = 0; int count = 0; void (*write_region)(struct nmgregion *, const struct db_full_path *, int, int, float [3]); if (!tsp || !pathp || !client_data) { bu_log("INTERNAL ERROR: gcv_region_end_mc missing parameters\n"); return TREE_NULL; } write_region = ((struct gcv_data *)client_data)->func; if (!write_region) { bu_log("INTERNAL ERROR: gcv_region_end missing conversion callback function\n"); return TREE_NULL; } RT_CK_FULL_PATH(pathp); RT_CK_TREE(curtree); RT_CK_TESS_TOL(tsp->ts_ttol); BN_CK_TOL(tsp->ts_tol); NMG_CK_MODEL(*tsp->ts_m); BU_LIST_INIT(&vhead); /* if (curtree->tr_op == OP_NOP) return 0; */ /* get a copy to play with as the parameters might get clobbered * by a longjmp. FIXME: db_dup_subtree() doesn't create real copies */ tp = db_dup_subtree(curtree, &rt_uniresource); /* FIXME: we can't free curtree until we get a "real" copy form * db_dup_subtree(). right now we get a fake copy just so we can * keep the compiler quiet about clobbering curtree during longjmp */ /* db_free_tree(curtree, &rt_uniresource); */ /* Sometimes the NMG library adds debugging bits when it detects * an internal error, before bombing. Stash. */ NMG_debug_state = RTG.NMG_debug; m = nmg_mmr(); r = nmg_mrsv(m); s = BU_LIST_FIRST(shell, &r->s_hd); if (tsp->ts_rtip == NULL) tsp->ts_rtip = rt_new_rti(tsp->ts_dbip); count += nmg_mc_evaluate (s, tsp->ts_rtip, pathp, tsp->ts_ttol, tsp->ts_tol); /* empty region? */ if (count == 0) { bu_log("Region %s appears to be empty.\n", db_path_to_string(pathp)); return TREE_NULL; } /* bu_log("Target is shot, %d triangles seen.\n", count); bu_log("Fusing\n"); fflush(stdout); nmg_model_fuse(m, tsp->ts_tol); bu_log("Done\n"); fflush(stdout); */ /* Kill cracks */ while (BU_LIST_NOT_HEAD(&s->l, &r->s_hd)) { struct shell *next_s; next_s = BU_LIST_PNEXT(shell, &s->l); if (nmg_kill_cracks(s)) { if (nmg_ks(s)) { empty_region = 1; break; } } /* nmg_shell_coplanar_face_merge(s, tsp->ts_tol, 42); */ s = next_s; } if (empty_region) return _gcv_cleanup(NMG_debug_state, tp); /* kill zero length edgeuses */ empty_model = nmg_kill_zero_length_edgeuses(*tsp->ts_m); if (empty_model) return _gcv_cleanup(NMG_debug_state, tp); if (BU_SETJUMP) { /* Error, bail out */ char *sofar; /* Relinquish bomb protection */ BU_UNSETJUMP; sofar = db_path_to_string(pathp); bu_log("FAILED in triangulator: %s\n", sofar); bu_free((char *)sofar, "sofar"); /* Release any intersector 2d tables */ nmg_isect2d_final_cleanup(); /* Get rid of (m)any other intermediate structures */ if ((*tsp->ts_m)->magic == NMG_MODEL_MAGIC) nmg_km(*tsp->ts_m); else bu_log("WARNING: tsp->ts_m pointer corrupted, ignoring it.\n"); /* Now, make a new, clean model structure for next pass. */ *tsp->ts_m = nmg_mm(); nmg_kr(r); return _gcv_cleanup(NMG_debug_state, tp); } else { /* Write the region out */ write_region(r, pathp, tsp->ts_regionid, tsp->ts_gmater, tsp->ts_mater.ma_color); } BU_UNSETJUMP; /* Relinquish bomb protection */ nmg_kr(r); return _gcv_cleanup(NMG_debug_state, tp); }
/** * 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 */ }
void pop_gop(int gop, char *parent1_id, char *parent2_id, char *child1_id, char *child2_id, struct db_i *dbi_p, struct db_i *dbi_c, struct resource *resp) { struct rt_db_internal in1, in2; struct rt_comb_internal *parent1; struct rt_comb_internal *parent2; struct directory *dp; union tree *cpoint, **cross_parent; struct node *add; int i = 0; struct node *chosen_node; int rand_node; RT_CHECK_DBI( dbi_p ); RT_CHECK_DBI( dbi_c ); RT_CK_RESOURCE( resp ); crossover_point = (union tree *)NULL; crossover_parent = (union tree **)NULL; node = (struct node*)NULL; if ( !rt_db_lookup_internal(dbi_p, parent1_id, &dp, &in1, LOOKUP_NOISY, &rt_uniresource)) bu_exit(EXIT_FAILURE, "Failed to read parent1"); shape_number =num_nodes= 0; parent1 = (struct rt_comb_internal *)in1.idb_ptr; mutate = 0; switch (gop) { case REPRODUCE: pop_functree(dbi_p, dbi_c, parent1->tree, resp, child1_id); break; case CROSSOVER: crossover = 1; /*load other parent */ if ( !rt_db_lookup_internal(dbi_p, parent2_id, &dp, &in2, LOOKUP_NOISY, resp)) bu_exit(EXIT_FAILURE, "Failed to read parent2"); parent2 = (struct rt_comb_internal *)in2.idb_ptr; BU_ALLOC(node, struct node); BU_LIST_INIT(&node->l); chosen_node = NULL; do{ num_nodes = 0; crossover_parent = &parent1->tree; crossover_node = (int)(pop_rand() * db_count_tree_nodes(parent1->tree, 0)); node_idx = 0; pop_functree(dbi_p, dbi_c, parent1->tree, resp, NULL); cross_parent = crossover_parent; cpoint = crossover_point; crossover_op = crossover_point->tr_op; #define MASK (OP_UNION | OP_XOR | OP_SUBTRACT|OP_INTERSECT) if (crossover_op & MASK)crossover_op = MASK; crossover_node = db_count_tree_nodes(crossover_point, 0); if (pop_find_nodes(parent2->tree) == crossover_node) { BU_ALLOC(add, struct node); add->s_parent = &parent2->tree; add->s_child = parent2->tree; BU_LIST_INSERT(&node->l, &add->l); ++num_nodes; } if (num_nodes > 0) { rand_node = (int)(pop_rand() * num_nodes); for (add=BU_LIST_FIRST(node, &node->l);BU_LIST_NOT_HEAD(add, &node->l) && chosen_node == NULL; add=BU_LIST_PNEXT(node, add)) { if (i++ == rand_node) { chosen_node = add; /* break cleanly...? */ } } } }while(chosen_node == NULL); /* cross trees */ *cross_parent = chosen_node->s_child; *chosen_node->s_parent =cpoint; while (BU_LIST_WHILE(add, node, &node->l)) { BU_LIST_DEQUEUE(&add->l); bu_free(add, "node"); } bu_free(node, "node"); crossover = 0; /*duplicate shapes held in trees*/ pop_functree(dbi_p, dbi_c, parent1->tree, resp, child1_id); shape_number = 0; pop_functree(dbi_p, dbi_c, parent2->tree, resp, child2_id); if ((dp = db_diradd(dbi_c, child2_id, -1, 0, dp->d_flags, (genptr_t)&dp->d_minor_type)) == RT_DIR_NULL) bu_exit(EXIT_FAILURE, "Failed to add new individual to child database"); if (rt_db_put_internal(dp, dbi_c, &in2, resp) < 0) bu_exit(EXIT_FAILURE, "Database write failure"); rt_db_free_internal(&in2); break; case MUTATE: crossover_parent = &parent1->tree; crossover_node = (int)(pop_rand() * db_count_tree_nodes(parent1->tree, 0)); node_idx = 0; mutate = 1; pop_functree(dbi_p, dbi_c, parent1->tree, resp, child1_id); mutate = 0; break; /* //random node to mutate n = (int)(pop_rand() * db_count_tree_nodes(parent1->tree, 0)); s_parent = &parent1->tree; s_node = n; node = 0; //find node pop_functree(dbi_p, dbi_c, parent1->tree, resp, NULL); */ default: bu_exit(EXIT_FAILURE, "illegal genetic operator\nfailed to execute genetic op"); } if ((dp=db_diradd(dbi_c, child1_id, -1, 0, dp->d_flags, (genptr_t)&dp->d_minor_type)) == RT_DIR_NULL) { bu_exit(EXIT_FAILURE, "Failed to add new individual to child database"); } if (rt_db_put_internal(dp, dbi_c, &in1, resp) < 0) bu_exit(EXIT_FAILURE, "Database write failure"); rt_db_free_internal(&in1); }
/* * Called from db_walk_tree(). * * This routine must be prepared to run in parallel. */ union tree * do_region_end(struct db_tree_state *tsp, const struct db_full_path *pathp, union tree *curtree, void *UNUSED(client_data)) { union tree *ret_tree = NULL; struct bu_list vhead; /* static due to longjmp */ static struct nmgregion *r = NULL; RT_CK_FULL_PATH(pathp); RT_CK_TREE(curtree); RT_CK_TESS_TOL(tsp->ts_ttol); BN_CK_TOL(tsp->ts_tol); NMG_CK_MODEL(*tsp->ts_m); BU_LIST_INIT(&vhead); if (RT_G_DEBUG&DEBUG_TREEWALK || verbose) { char *sofar = db_path_to_string(pathp); bu_log("\ndo_region_end(%d %d%%) %s\n", regions_tried, regions_tried>0 ? (regions_converted * 100) / regions_tried : 0, sofar); bu_free(sofar, "path string"); } if (curtree->tr_op == OP_NOP) return curtree; regions_tried++; /* do the deed */ ret_tree = process_region(pathp, curtree, tsp); if (ret_tree) r = ret_tree->tr_d.td_r; else { if (verbose) { printf("\tNothing left of this region after Boolean evaluation\n"); fprintf(fpe, "WARNING: Nothing left after Boolean evaluation: %s\n", db_path_to_string(pathp)); fflush(fpe); } regions_written++; /* don't count as a failure */ r = (struct nmgregion *)NULL; } regions_converted++; if (r != (struct nmgregion *)NULL) { struct shell *s; int empty_region=0; int empty_model=0; /* Kill cracks */ s = BU_LIST_FIRST(shell, &r->s_hd); while (BU_LIST_NOT_HEAD(&s->l, &r->s_hd)) { struct shell *next_s; next_s = BU_LIST_PNEXT(shell, &s->l); if (nmg_kill_cracks(s)) { if (nmg_ks(s)) { empty_region = 1; break; } } s = next_s; } /* kill zero length edgeuses */ if (!empty_region) { empty_model = nmg_kill_zero_length_edgeuses(*tsp->ts_m); } if (!empty_region && !empty_model) { if (!BU_SETJUMP) { /* try */ /* Write the region to the TANKILL file */ nmg_to_acad(r, pathp, tsp->ts_regionid); regions_written++; } else { /* catch */ char *sofar; BU_UNSETJUMP; sofar = db_path_to_string(pathp); bu_free((char *)sofar, "sofar"); /* Sometimes the NMG library adds debugging bits when * it detects an internal error, before bombing out. */ RTG.NMG_debug = NMG_debug; /* restore mode */ /* Release any intersector 2d tables */ nmg_isect2d_final_cleanup(); /* Get rid of (m)any other intermediate structures */ if ((*tsp->ts_m)->magic == NMG_MODEL_MAGIC) { nmg_km(*tsp->ts_m); } else { bu_log("WARNING: tsp->ts_m pointer corrupted, ignoring it.\n"); } /* Now, make a new, clean model structure for next pass. */ *tsp->ts_m = nmg_mm(); /* FIXME: leaking memory with curtree */ return TREE_NULL; } BU_UNSETJUMP; } if (!empty_model) nmg_kr(r); } /* * Dispose of original tree, so that all associated dynamic * memory is released now, not at the end of all regions. * A return of TREE_NULL from this routine signals an error, * and there is no point to adding _another_ message to our output, * so we need to cons up an OP_NOP node to return. */ if (regions_tried>0) { float npercent, tpercent; npercent = (float)(regions_converted * 100) / regions_tried; tpercent = (float)(regions_written * 100) / regions_tried; printf("Tried %d regions, %d conv. to NMG's %d conv. to tri. nmgper = %.2f%% triper = %.2f%% \n", regions_tried, regions_converted, regions_written, npercent, tpercent); } BU_ALLOC(curtree, union tree); RT_TREE_INIT(curtree); curtree->tr_op = OP_NOP; return curtree; }
/** * Read a polygon file and convert it to an NMG shell * * A polygon file consists of the following: * * The first line consists of two integer numbers: the number of * points (vertices) in the file, followed by the number of polygons * in the file. This line is followed by lines for each of the * vertices. Each vertex is listed on its own line, as the 3tuple "X * Y Z". After the list of vertices comes the list of polygons. * each polygon is represented by a line containing 1) the number of * vertices in the polygon, followed by 2) the indices of the * vertices that make up the polygon. * * Implicitly returns r->s_p which is a new shell containing all the * faces from the polygon file. * * XXX This is a horrible way to do this. Lee violates his own rules * about not creating fundamental structures on his own... :-) * Retired in favor of more modern tessellation strategies. */ struct shell * nmg_polytonmg(FILE *fp, struct nmgregion *r, const struct bn_tol *tol) { int i, j, num_pts, num_facets, pts_this_face, facet; int vl_len; struct vertex **v; /* list of all vertices */ struct vertex **vl; /* list of vertices for this polygon*/ point_t p; struct shell *s; struct faceuse *fu; struct loopuse *lu; struct edgeuse *eu; plane_t plane; struct model *m; s = nmg_msv(r); m = s->r_p->m_p; nmg_kvu(s->vu_p); /* get number of points & number of facets in file */ if (fscanf(fp, "%d %d", &num_pts, &num_facets) != 2) bu_bomb("polytonmg() Error in first line of poly file\n"); else if (RTG.NMG_debug & DEBUG_POLYTO) bu_log("points: %d facets: %d\n", num_pts, num_facets); v = (struct vertex **) bu_calloc(num_pts, sizeof (struct vertex *), "vertices"); /* build the vertices */ for (i = 0; i < num_pts; ++i) { GET_VERTEX(v[i], m); v[i]->magic = NMG_VERTEX_MAGIC; } /* read in the coordinates of the vertices */ for (i=0; i < num_pts; ++i) { if (fscanf(fp, "%lg %lg %lg", &p[0], &p[1], &p[2]) != 3) bu_bomb("polytonmg() Error reading point"); else if (RTG.NMG_debug & DEBUG_POLYTO) bu_log("read vertex #%d (%g %g %g)\n", i, p[0], p[1], p[2]); nmg_vertex_gv(v[i], p); } vl = (struct vertex **)bu_calloc(vl_len=8, sizeof (struct vertex *), "vertex parameter list"); for (facet = 0; facet < num_facets; ++facet) { if (fscanf(fp, "%d", &pts_this_face) != 1) bu_bomb("polytonmg() error getting pt count for this face"); if (RTG.NMG_debug & DEBUG_POLYTO) bu_log("facet %d pts in face %d\n", facet, pts_this_face); if (pts_this_face > vl_len) { while (vl_len < pts_this_face) vl_len *= 2; vl = (struct vertex **)bu_realloc((char *)vl, vl_len*sizeof(struct vertex *), "vertex parameter list (realloc)"); } for (i=0; i < pts_this_face; ++i) { if (fscanf(fp, "%d", &j) != 1) bu_bomb("polytonmg() error getting point index for v in f"); vl[i] = v[j-1]; } fu = nmg_cface(s, vl, pts_this_face); lu = BU_LIST_FIRST(loopuse, &fu->lu_hd); /* XXX should check for vertex-loop */ eu = BU_LIST_FIRST(edgeuse, &lu->down_hd); NMG_CK_EDGEUSE(eu); if (bn_mk_plane_3pts(plane, eu->vu_p->v_p->vg_p->coord, BU_LIST_PNEXT(edgeuse, eu)->vu_p->v_p->vg_p->coord, BU_LIST_PLAST(edgeuse, eu)->vu_p->v_p->vg_p->coord, tol)) { bu_log("At %d in %s\n", __LINE__, __FILE__); bu_bomb("polytonmg() cannot make plane equation\n"); } else nmg_face_g(fu, plane); } for (i=0; i < num_pts; ++i) { if (BU_LIST_IS_EMPTY(&v[i]->vu_hd)) continue; FREE_VERTEX(v[i]); } bu_free((char *)v, "vertex array"); return s; }
void process_non_light(struct model *m) { /* static due to bu exception handling */ static struct shell *s; static struct shell *next_s; static struct faceuse *fu; static struct faceuse *next_fu; static struct loopuse *lu; static struct nmgregion *reg; /* triangulate any faceuses with holes */ for ( BU_LIST_FOR( reg, nmgregion, &m->r_hd ) ) { NMG_CK_REGION( reg ); s = BU_LIST_FIRST( shell, ®->s_hd ); while ( BU_LIST_NOT_HEAD( s, ®->s_hd ) ) { NMG_CK_SHELL( s ); next_s = BU_LIST_PNEXT( shell, &s->l ); fu = BU_LIST_FIRST( faceuse, &s->fu_hd ); while ( BU_LIST_NOT_HEAD( &fu->l, &s->fu_hd ) ) { int shell_is_dead=0; NMG_CK_FACEUSE( fu ); next_fu = BU_LIST_PNEXT( faceuse, &fu->l ); if ( fu->orientation != OT_SAME ) { fu = next_fu; continue; } if ( fu->fumate_p == next_fu ) { /* make sure next_fu is not the mate of fu */ next_fu = BU_LIST_PNEXT( faceuse, &next_fu->l ); } /* check if this faceuse has any holes */ for ( BU_LIST_FOR( lu, loopuse, &fu->lu_hd ) ) { NMG_CK_LOOPUSE( lu ); if ( lu->orientation == OT_OPPOSITE ) { /* this is a hole, so * triangulate the faceuse */ if ( !BU_SETJUMP ) { /* try */ if ( nmg_triangulate_fu( fu, &tol ) ) { if ( nmg_kfu( fu ) ) { (void) nmg_ks( s ); shell_is_dead = 1; } } } else { /* catch */ bu_log( "A face has failed triangulation!\n" ); if ( next_fu == fu->fumate_p ) next_fu = BU_LIST_PNEXT( faceuse, &next_fu->l ); if ( nmg_kfu( fu ) ) { (void) nmg_ks( s ); shell_is_dead = 1; } } BU_UNSETJUMP; break; } } if ( shell_is_dead ) break; fu = next_fu; } s = next_s; } } }
/* * Called from db_walk_tree(). * * This routine must be prepared to run in parallel. */ union tree *do_region_end(struct db_tree_state *tsp, const struct db_full_path *pathp, union tree *curtree, void *UNUSED(client_data)) { union tree *ret_tree; struct bu_list vhead; struct nmgregion *r; RT_CK_FULL_PATH(pathp); RT_CK_TREE(curtree); RT_CK_TESS_TOL(tsp->ts_ttol); BN_CK_TOL(tsp->ts_tol); NMG_CK_MODEL(*tsp->ts_m); BU_LIST_INIT(&vhead); { char *sofar = db_path_to_string(pathp); bu_log("\ndo_region_end(%d %d%%) %s\n", regions_tried, regions_tried>0 ? (regions_converted * 100) / regions_tried : 0, sofar); bu_free(sofar, "path string"); } if (curtree->tr_op == OP_NOP) return curtree; regions_tried++; if (verbose) bu_log("Attempting to process region %s\n", db_path_to_string(pathp)); ret_tree= process_boolean(curtree, tsp, pathp); if (ret_tree) r = ret_tree->tr_d.td_r; else { if (verbose) bu_log("\tNothing left of this region after Boolean evaluation\n"); regions_written++; /* don't count as a failure */ r = (struct nmgregion *)NULL; } regions_converted++; if (r != (struct nmgregion *)NULL) { struct shell *s; int empty_region=0; int empty_model=0; /* Kill cracks */ s = BU_LIST_FIRST(shell, &r->s_hd); while (BU_LIST_NOT_HEAD(&s->l, &r->s_hd)) { struct shell *next_s; next_s = BU_LIST_PNEXT(shell, &s->l); if (nmg_kill_cracks(s)) { if (nmg_ks(s)) { empty_region = 1; break; } } s = next_s; } /* kill zero length edgeuses */ if (!empty_region) { empty_model = nmg_kill_zero_length_edgeuses(*tsp->ts_m); } if (!empty_region && !empty_model) { process_triangulation(r, pathp, tsp); regions_written++; } if (!empty_model) nmg_kr(r); } /* * Dispose of original tree, so that all associated dynamic * memory is released now, not at the end of all regions. * A return of TREE_NULL from this routine signals an error, * and there is no point to adding _another_ message to our output, * so we need to cons up an OP_NOP node to return. */ db_free_tree(curtree, &rt_uniresource); /* Does an nmg_kr() */ BU_ALLOC(curtree, union tree); RT_TREE_INIT(curtree); curtree->tr_op = OP_NOP; return curtree; }
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) { v = BU_LIST_PNEXT(vertexuse, &lu->down_hd)->v_p; NMG_CK_VERTEX(v); cnt++; } else bu_bomb("verts_in_nmg_loop: bad loopuse\n"); return cnt; } /** * Count number of vertices in an NMG face. */ static int verts_in_nmg_face(struct faceuse *fu) { int cnt;