static union tree * process_region(const struct db_full_path *pathp, union tree *curtree, struct db_tree_state *tsp) { /* Begin bomb protection */ if (!BU_SETJUMP) { /* try */ union tree *ret_tree; printf("Attempting to process region %s\n", db_path_to_string(pathp)); fflush(stdout); ret_tree = nmg_booltree_evaluate(curtree, tsp->ts_tol, &rt_uniresource); if (ret_tree != curtree) { db_free_tree(curtree, &rt_uniresource); } return ret_tree; } else { /* catch */ /* Error, bail out */ char *sofar; BU_UNSETJUMP; /* Relinquish the protection */ sofar = db_path_to_string(pathp); bu_log("FAILED in Boolean evaluation: %s\n", sofar); fprintf(fpe, "Failed Bool. Eval.: %s\n", sofar); fflush(fpe); 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(); /* Release the tree memory & input regions */ /* FIXME: memory leak? */ /* db_free_tree(curtree);*/ /* Does an nmg_kr() */ /* 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(); return TREE_NULL; } }
HIDDEN void wdb_free_tokens(struct bu_list *hp) { struct tokens *tok; BU_CK_LIST_HEAD(hp); while (BU_LIST_WHILE(tok, tokens, hp)) { BU_LIST_DEQUEUE(&tok->l); if (tok->type == WDB_TOK_TREE) { db_free_tree(tok->tp, &rt_uniresource); } } }
static union tree * process_boolean(union tree *curtree, struct db_tree_state *tsp, const struct db_full_path *pathp) { union tree *ret_tree = TREE_NULL; /* Begin bomb protection */ if (!BU_SETJUMP) { /* try */ (void)nmg_model_fuse(*tsp->ts_m, tsp->ts_tol); ret_tree = nmg_booltree_evaluate(curtree, tsp->ts_tol, &rt_uniresource); } else { /* catch */ char *name = db_path_to_string(pathp); /* Error, bail out */ bu_log("conversion of %s FAILED!\n", name); /* Sometimes the NMG library adds debugging bits when * it detects an internal error, before before bombing out. */ RTG.NMG_debug = NMG_debug;/* restore mode */ /* Release any intersector 2d tables */ nmg_isect2d_final_cleanup(); /* Release the tree memory & input regions */ db_free_tree(curtree, &rt_uniresource);/* Does an nmg_kr() */ /* 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"); } bu_free(name, "db_path_to_string"); /* Now, make a new, clean model structure for next pass. */ *tsp->ts_m = nmg_mm(); } BU_UNSETJUMP;/* Relinquish the protection */ return ret_tree; }
static union tree * process_boolean(struct db_tree_state *tsp, union tree *curtree, const struct db_full_path *pathp) { union tree *result = NULL; /* Begin bomb protection */ if (!BU_SETJUMP) { /* try */ (void)nmg_model_fuse(*tsp->ts_m, tsp->ts_tol); result = nmg_booltree_evaluate(curtree, tsp->ts_tol, &rt_uniresource); } else { /* catch */ char *sofar; /* Error, bail out */ sofar = db_path_to_string(pathp); bu_log("FAILED: Cannot convert %s!\n", sofar); bu_free(sofar, "path string"); /* Sometimes the NMG library adds debugging bits when * it detects an internal error, before bombing out. */ RTG.NMG_debug = NMG_debug; /* restore mode */ /* Release the tree memory & input regions */ db_free_tree(curtree, &rt_uniresource); /* Does an nmg_kr() */ /* Get rid of (m)any other intermediate structures */ if ((*tsp->ts_m)->magic == NMG_MODEL_MAGIC) nmg_km(*tsp->ts_m); /* Now, make a new, clean model structure for next pass. */ *tsp->ts_m = nmg_mm(); } BU_UNSETJUMP; /* Relinquish the protection */ return result; }
/* * 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; }
int ged_bev(struct ged *gedp, int argc, const char *argv[]) { static const char *usage = "[P|t] new_obj obj1 op obj2 op obj3 ..."; int i; int c; int ncpu; char *cmdname; char *newname; struct rt_db_internal intern; struct directory *dp; char op; int failed; /* static due to longjmp */ static int triangulate = 0; static union tree *tmp_tree = NULL; GED_CHECK_DATABASE_OPEN(gedp, GED_ERROR); GED_CHECK_READ_ONLY(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) { bu_vls_printf(gedp->ged_result_str, "Usage: %s %s", argv[0], usage); return GED_ERROR; } cmdname = (char *)argv[0]; /* Establish tolerances */ gedp->ged_wdbp->wdb_initial_tree_state.ts_ttol = &gedp->ged_wdbp->wdb_ttol; gedp->ged_wdbp->wdb_initial_tree_state.ts_tol = &gedp->ged_wdbp->wdb_tol; gedp->ged_wdbp->wdb_ttol.magic = RT_TESS_TOL_MAGIC; /* Initial values for options, must be reset each time */ ncpu = 1; triangulate = 0; /* Parse options. */ bu_optind = 1; /* re-init bu_getopt() */ while ((c=bu_getopt(argc, (char * const *)argv, "tP:")) != -1) { switch (c) { case 'P': #if 0 /* not yet supported */ ncpu = atoi(bu_optarg); #endif break; case 't': triangulate = 1; break; default: { bu_vls_printf(gedp->ged_result_str, "%s: option '%c' unknown\n", cmdname, c); } break; } } argc -= bu_optind; argv += bu_optind; newname = (char *)argv[0]; argv++; argc--; if (argc < 1) { bu_vls_printf(gedp->ged_result_str, "%s: Nothing to evaluate!!!\n", cmdname); return GED_ERROR; } GED_CHECK_EXISTS(gedp, newname, LOOKUP_QUIET, GED_ERROR); bu_vls_printf(gedp->ged_result_str, "%s: tessellating primitives with tolerances a=%g, r=%g, n=%g\n", argv[0], gedp->ged_wdbp->wdb_ttol.abs, gedp->ged_wdbp->wdb_ttol.rel, gedp->ged_wdbp->wdb_ttol.norm); bev_facetize_tree = (union tree *)0; bev_nmg_model = nmg_mm(); gedp->ged_wdbp->wdb_initial_tree_state.ts_m = &bev_nmg_model; op = ' '; tmp_tree = (union tree *)NULL; while (argc) { i = db_walk_tree(gedp->ged_wdbp->dbip, 1, (const char **)argv, ncpu, &gedp->ged_wdbp->wdb_initial_tree_state, 0, /* take all regions */ bev_facetize_region_end, nmg_booltree_leaf_tess, (genptr_t)gedp); if (i < 0) { bu_vls_printf(gedp->ged_result_str, "%s: error in db_walk_tree()\n", cmdname); /* Destroy NMG */ nmg_km(bev_nmg_model); return GED_ERROR; } argc--; argv++; if (tmp_tree && op != ' ') { union tree *new_tree; BU_ALLOC(new_tree, union tree); RT_TREE_INIT(new_tree); new_tree->tr_b.tb_regionp = REGION_NULL; new_tree->tr_b.tb_left = tmp_tree; new_tree->tr_b.tb_right = bev_facetize_tree; switch (op) { case 'u': case 'U': new_tree->tr_op = OP_UNION; break; case '-': new_tree->tr_op = OP_SUBTRACT; break; case '+': new_tree->tr_op = OP_INTERSECT; break; default: { bu_vls_printf(gedp->ged_result_str, "%s: Unrecognized operator: (%c)\nAborting\n", argv[0], op); db_free_tree(bev_facetize_tree, &rt_uniresource); nmg_km(bev_nmg_model); return GED_ERROR; } } tmp_tree = new_tree; bev_facetize_tree = (union tree *)NULL; } else if (!tmp_tree && op == ' ') { /* just starting out */ tmp_tree = bev_facetize_tree; bev_facetize_tree = (union tree *)NULL; } if (argc) { op = *argv[0]; argc--; argv++; } else op = ' '; } if (tmp_tree) { /* Now, evaluate the boolean tree into ONE region */ bu_vls_printf(gedp->ged_result_str, "%s: evaluating boolean expressions\n", cmdname); if (BU_SETJUMP) { BU_UNSETJUMP; bu_vls_printf(gedp->ged_result_str, "%s: WARNING: Boolean evaluation failed!!!\n", cmdname); if (tmp_tree) db_free_tree(tmp_tree, &rt_uniresource); tmp_tree = (union tree *)NULL; nmg_km(bev_nmg_model); bev_nmg_model = (struct model *)NULL; return GED_ERROR; } failed = nmg_boolean(tmp_tree, bev_nmg_model, &gedp->ged_wdbp->wdb_tol, &rt_uniresource); BU_UNSETJUMP; } else failed = 1; if (failed) { bu_vls_printf(gedp->ged_result_str, "%s: no resulting region, aborting\n", cmdname); if (tmp_tree) db_free_tree(tmp_tree, &rt_uniresource); tmp_tree = (union tree *)NULL; nmg_km(bev_nmg_model); bev_nmg_model = (struct model *)NULL; return GED_ERROR; } /* New region remains part of this nmg "model" */ NMG_CK_REGION(tmp_tree->tr_d.td_r); bu_vls_printf(gedp->ged_result_str, "%s: facetize %s\n", cmdname, tmp_tree->tr_d.td_name); nmg_vmodel(bev_nmg_model); /* Triangulate model, if requested */ if (triangulate) { bu_vls_printf(gedp->ged_result_str, "%s: triangulating resulting object\n", cmdname); if (BU_SETJUMP) { BU_UNSETJUMP; bu_vls_printf(gedp->ged_result_str, "%s: WARNING: Triangulation failed!!!\n", cmdname); if (tmp_tree) db_free_tree(tmp_tree, &rt_uniresource); tmp_tree = (union tree *)NULL; nmg_km(bev_nmg_model); bev_nmg_model = (struct model *)NULL; return GED_ERROR; } nmg_triangulate_model(bev_nmg_model, &gedp->ged_wdbp->wdb_tol); BU_UNSETJUMP; } bu_vls_printf(gedp->ged_result_str, "%s: converting NMG to database format\n", cmdname); /* Export NMG as a new solid */ RT_DB_INTERNAL_INIT(&intern); intern.idb_major_type = DB5_MAJORTYPE_BRLCAD; intern.idb_type = ID_NMG; intern.idb_meth = &rt_functab[ID_NMG]; intern.idb_ptr = (genptr_t)bev_nmg_model; bev_nmg_model = (struct model *)NULL; GED_DB_DIRADD(gedp, dp, newname, RT_DIR_PHONY_ADDR, 0, RT_DIR_SOLID, (genptr_t)&intern.idb_type, GED_ERROR); GED_DB_PUT_INTERNAL(gedp, dp, &intern, &rt_uniresource, GED_ERROR); tmp_tree->tr_d.td_r = (struct nmgregion *)NULL; /* Free boolean tree, and the regions in it. */ db_free_tree(tmp_tree, &rt_uniresource); return GED_OK; }
/* * D O _ R E G I O N _ E N D * * Called from db_walk_tree(). * * This routine must be prepared to run in parallel. */ union tree *do_region_end(register struct db_tree_state *tsp, struct db_full_path *pathp, union tree *curtree, genptr_t client_data) { union tree *ret_tree; struct nmgregion *r; struct bu_list vhead; 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_done * 100) / regions_tried : 0, sofar); bu_free(sofar, "path string"); } if (curtree->tr_op == OP_NOP) return curtree; regions_tried++; /* Begin bomb protection */ if ( ncpu == 1 ) { if ( BU_SETJUMP ) { /* Error, bail out */ BU_UNSETJUMP; /* Relinquish the protection */ /* Sometimes the NMG library adds debugging bits when * it detects an internal error, before bombing out. */ rt_g.NMG_debug = NMG_debug; /* restore mode */ /* Release the tree memory & input regions */ db_free_tree(curtree, &rt_uniresource); /* Does an nmg_kr() */ /* Get rid of (m)any other intermediate structures */ if ( (*tsp->ts_m)->magic != -1L ) nmg_km(*tsp->ts_m); /* Now, make a new, clean model structure for next pass. */ *tsp->ts_m = nmg_mm(); goto out; } } (void)nmg_model_fuse(*tsp->ts_m, tsp->ts_tol); ret_tree = nmg_booltree_evaluate(curtree, tsp->ts_tol, &rt_uniresource); /* librt/nmg_bool.c */ BU_UNSETJUMP; /* Relinquish the protection */ if ( ret_tree ) r = ret_tree->tr_d.td_r; else r = (struct nmgregion *)NULL; regions_done++; if (r != 0) { FILE *fp_psurf; int i; struct bu_vls file_base; struct bu_vls file; bu_vls_init(&file_base); bu_vls_init(&file); bu_vls_strcpy(&file_base, prefix); bu_vls_strcat(&file_base, DB_FULL_PATH_CUR_DIR(pathp)->d_namep); /* Dots confuse Jack's Peabody language. Change to '_'. */ for (i = 0; i < file_base.vls_len; i++) if (file_base.vls_str[i] == '.') file_base.vls_str[i] = '_'; /* Write color attribute to .fig figure file. */ if (tsp->ts_mater.ma_color_valid != 0) { fprintf(fp_fig, "\tattribute %s {\n", bu_vls_addr(&file_base)); fprintf(fp_fig, "\t\trgb = (%f, %f, %f);\n", V3ARGS(tsp->ts_mater.ma_color)); fprintf(fp_fig, "\t\tambient = 0.18;\n"); fprintf(fp_fig, "\t\tdiffuse = 0.72;\n"); fprintf(fp_fig, "\t}\n"); } /* Write segment attributes to .fig figure file. */ fprintf(fp_fig, "\tsegment %s_seg {\n", bu_vls_addr(&file_base)); fprintf(fp_fig, "\t\tpsurf=\"%s.pss\";\n", bu_vls_addr(&file_base)); if (tsp->ts_mater.ma_color_valid != 0) fprintf(fp_fig, "\t\tattribute=%s;\n", bu_vls_addr(&file_base)); fprintf(fp_fig, "\t\tsite base->location=trans(0, 0, 0);\n"); fprintf(fp_fig, "\t}\n"); if ( bu_vls_strlen(&base_seg) <= 0 ) { bu_vls_vlscat( &base_seg, &file_base ); } else { fprintf(fp_fig, "\tjoint %s_jt {\n", bu_vls_addr(&file_base)); fprintf(fp_fig, "\t\tconnect %s_seg.base to %s_seg.base;\n", bu_vls_addr(&file_base), bu_vls_addr(&base_seg) ); fprintf(fp_fig, "\t}\n"); } bu_vls_vlscat(&file, &file_base); bu_vls_strcat(&file, ".pss"); /* Required Jack suffix. */ /* Write psurf to .pss file. */ if ((fp_psurf = fopen(bu_vls_addr(&file), "wb")) == NULL) perror(bu_vls_addr(&file)); else { nmg_to_psurf(r, fp_psurf); fclose(fp_psurf); if (verbose) bu_log("*** Wrote %s\n", bu_vls_addr(&file)); } bu_vls_free(&file); /* Also write as UNIX-plot file, if desired */ if ( debug_plots ) { FILE *fp; bu_vls_vlscat(&file, &file_base); bu_vls_strcat(&file, ".pl"); if ((fp = fopen(bu_vls_addr(&file), "wb")) == NULL) perror(bu_vls_addr(&file)); else { struct bu_list vhead; pl_color( fp, (int)(tsp->ts_mater.ma_color[0] * 255), (int)(tsp->ts_mater.ma_color[1] * 255), (int)(tsp->ts_mater.ma_color[2] * 255) ); /* nmg_pl_r( fp, r ); */ BU_LIST_INIT( &vhead ); nmg_r_to_vlist( &vhead, r, 0 ); rt_vlist_to_uplot( fp, &vhead ); fclose(fp); if (verbose) bu_log("*** Wrote %s\n", bu_vls_addr(&file)); } bu_vls_free(&file); } /* NMG region is no longer necessary */ 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() */ out: BU_GETUNION(curtree, tree); curtree->magic = RT_TREE_MAGIC; curtree->tr_op = OP_NOP; return(curtree); }
/* * D O _ R E G I O N _ E N D * * 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, genptr_t UNUSED(client_data)) { union tree *ret_tree; struct nmgregion *r; RT_CK_TESS_TOL(tsp->ts_ttol); BN_CK_TOL(tsp->ts_tol); NMG_CK_MODEL(*tsp->ts_m); 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_done * 100) / regions_tried : 0, sofar); bu_free(sofar, "path string"); } if (curtree->tr_op == OP_NOP) return curtree; regions_tried++; ret_tree = process_boolean(curtree, tsp, pathp); if ( ret_tree ) r = ret_tree->tr_d.td_r; else r = (struct nmgregion *)NULL; regions_done++; if (r != 0) { FILE *fp_psurf; size_t i; struct bu_vls file_base = BU_VLS_INIT_ZERO; struct bu_vls file = BU_VLS_INIT_ZERO; bu_vls_strcpy(&file_base, prefix); bu_vls_strcat(&file_base, DB_FULL_PATH_CUR_DIR(pathp)->d_namep); /* Dots confuse Jack's Peabody language. Change to '_'. */ for (i = 0; i < file_base.vls_len; i++) if (file_base.vls_str[i] == '.') file_base.vls_str[i] = '_'; /* Write color attribute to .fig figure file. */ if (tsp->ts_mater.ma_color_valid != 0) { fprintf(fp_fig, "\tattribute %s {\n", bu_vls_addr(&file_base)); fprintf(fp_fig, "\t\trgb = (%f, %f, %f);\n", V3ARGS(tsp->ts_mater.ma_color)); fprintf(fp_fig, "\t\tambient = 0.18;\n"); fprintf(fp_fig, "\t\tdiffuse = 0.72;\n"); fprintf(fp_fig, "\t}\n"); } /* Write segment attributes to .fig figure file. */ fprintf(fp_fig, "\tsegment %s_seg {\n", bu_vls_addr(&file_base)); fprintf(fp_fig, "\t\tpsurf=\"%s.pss\";\n", bu_vls_addr(&file_base)); if (tsp->ts_mater.ma_color_valid != 0) fprintf(fp_fig, "\t\tattribute=%s;\n", bu_vls_addr(&file_base)); fprintf(fp_fig, "\t\tsite base->location=trans(0, 0, 0);\n"); fprintf(fp_fig, "\t}\n"); if ( bu_vls_strlen(&base_seg) <= 0 ) { bu_vls_vlscat( &base_seg, &file_base ); } else { fprintf(fp_fig, "\tjoint %s_jt {\n", bu_vls_addr(&file_base)); fprintf(fp_fig, "\t\tconnect %s_seg.base to %s_seg.base;\n", bu_vls_addr(&file_base), bu_vls_addr(&base_seg) ); fprintf(fp_fig, "\t}\n"); } bu_vls_vlscat(&file, &file_base); bu_vls_strcat(&file, ".pss"); /* Required Jack suffix. */ /* Write psurf to .pss file. */ if ((fp_psurf = fopen(bu_vls_addr(&file), "wb")) == NULL) perror(bu_vls_addr(&file)); else { nmg_to_psurf(r, fp_psurf); fclose(fp_psurf); if (verbose) bu_log("*** Wrote %s\n", bu_vls_addr(&file)); } bu_vls_free(&file); /* Also write as UNIX-plot file, if desired */ if ( debug_plots ) { FILE *fp; bu_vls_vlscat(&file, &file_base); bu_vls_strcat(&file, ".pl"); if ((fp = fopen(bu_vls_addr(&file), "wb")) == NULL) perror(bu_vls_addr(&file)); else { struct bu_list vhead; pl_color( fp, (int)(tsp->ts_mater.ma_color[0] * 255), (int)(tsp->ts_mater.ma_color[1] * 255), (int)(tsp->ts_mater.ma_color[2] * 255) ); /* nmg_pl_r( fp, r ); */ BU_LIST_INIT( &vhead ); nmg_r_to_vlist( &vhead, r, 0 ); rt_vlist_to_uplot( fp, &vhead ); fclose(fp); if (verbose) bu_log("*** Wrote %s\n", bu_vls_addr(&file)); } bu_vls_free(&file); } /* NMG region is no longer necessary */ 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 * 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; }
/* * Called from db_walk_tree(). * * This routine must be prepared to run in parallel. */ union tree * do_nmg_region_end(struct db_tree_state *tsp, const struct db_full_path *pathp, union tree *curtree, void *UNUSED(client_data)) { union tree *result; struct nmgregion *r; struct bu_list vhead; struct directory *dp; int dependent; size_t i; 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_nmg_region_end(%d %d%%) %s\n", regions_tried, regions_tried>0 ? (regions_done * 100) / regions_tried : 0, sofar); bu_free(sofar, "path string"); } if (curtree->tr_op == OP_NOP) return curtree; regions_tried++; if (verbose) bu_log("\ndoing boolean tree evaluate...\n"); /* evaluate the boolean */ result = process_boolean(tsp, curtree, pathp); if (result) r = result->tr_d.td_r; else r = (struct nmgregion *)NULL; if (verbose) bu_log("\nfinished boolean tree evaluate...\n"); regions_done++; if (r != NULL) { dp = DB_FULL_PATH_CUR_DIR(pathp); if (multi_file) { /* Open the output file */ if (output_file == NULL) fp_dir = stdout; else { char *multi_name; size_t len; int unique = 0; char suffix[SUFFIX_LEN+1]; /* construct a unique file name */ len = strlen(output_file) + strlen(dp->d_namep) + 6 + SUFFIX_LEN; multi_name = (char *)bu_malloc(sizeof(char)*len, "multi_name"); snprintf(multi_name, len, "%s/%s.igs", output_file, dp->d_namep); bu_strlcpy(suffix, "a", sizeof(suffix)); suffix[0]--; while (!unique) { if (bu_file_readable(multi_name)) { unique = 1; break; } /* not unique, try adding a suffix */ len = strlen(suffix); i = len - 1; suffix[i]++; while (suffix[i] > 'z' && i > 0) { suffix[i] = 'a'; i--; suffix[i]++; } if (suffix[0] > 'z' && len < SUFFIX_LEN) { for (i = 0; i <= len; i++) suffix[i] = 'a'; } else if (suffix[0] > 'z' && len >= SUFFIX_LEN) { bu_log("too many files with the same name (%s)\n", dp->d_namep); bu_exit(1, "Cannot create a unique filename, \n"); } snprintf(multi_name, len, "%s/%s%s.igs", output_file, dp->d_namep, suffix); } if ((fp_dir = fopen(multi_name, "wb")) == NULL) { perror("g-iges"); bu_exit(1, "Cannot open output file: %s\n", multi_name); } } /* Open the temporary file for the parameter section */ if ((fp_param = bu_temp_file(NULL, 0)) == NULL) { perror("g-iges"); bu_exit(1, "Cannot open temporary file\n"); } /* let the IGES routines know the selected tolerances and the database pointer */ iges_init(&tol, &ttol, verbose, DBIP); /* Write start and global sections of the IGES file */ w_start_global(fp_dir, fp_param, db_name, prog_name, output_file, __DATE__, brlcad_version()); } if (mode == FACET_MODE) { dependent = 1; for (i = 0; i < no_of_indeps; i++) { if (!bu_strncmp(dp->d_namep, independent[i], NAMESIZE+1)) { dependent = 0; break; } } dp->d_uses = (-nmgregion_to_iges(dp->d_namep, r, dependent, fp_dir, fp_param)); } else if (mode == TRIMMED_SURF_MODE) dp->d_uses = (-nmgregion_to_tsurf(dp->d_namep, r, fp_dir, fp_param)); /* NMG region is no longer necessary */ nmg_kr(r); if (multi_file) { char copy_buffer[CP_BUF_SIZE] = {0}; /* Copy the parameter section from the temporary file to the output file */ if ((bu_fseek(fp_param, 0, 0))) { perror("g-iges"); bu_exit(1, "Cannot seek to start of temporary file\n"); } while ((i = fread(copy_buffer, 1, CP_BUF_SIZE, fp_param))) if (fwrite(copy_buffer, 1, i, fp_dir) != i) { perror("g-iges"); bu_exit(1, "Error in copying parameter data to %s\n", output_file); } /* Write the terminate section */ w_terminate(fp_dir); fclose(fp_dir); fclose(fp_param); } } /* * 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; }
/** * This routine must be prepared to run in parallel. */ static union tree * draw_nmg_region_end(struct db_tree_state *tsp, const struct db_full_path *pathp, union tree *curtree, void *client_data) { struct nmgregion *r; struct bu_list vhead; int failed; struct _ged_client_data *dgcdp = (struct _ged_client_data *)client_data; RT_CK_TESS_TOL(tsp->ts_ttol); BN_CK_TOL(tsp->ts_tol); NMG_CK_MODEL(*tsp->ts_m); RT_CK_RESOURCE(tsp->ts_resp); BU_LIST_INIT(&vhead); if (RT_G_DEBUG&DEBUG_TREEWALK) { char *sofar = db_path_to_string(pathp); bu_vls_printf(dgcdp->gedp->ged_result_str, "nmg_region_end() path='%s'\n", sofar); bu_free((void *)sofar, "path string"); } else { char *sofar = db_path_to_string(pathp); bu_vls_printf(dgcdp->gedp->ged_result_str, "%s:\n", sofar); bu_free((void *)sofar, "path string"); } if (curtree->tr_op == OP_NOP) return curtree; failed = 1; if (!dgcdp->draw_nmg_only) { failed = process_boolean(curtree, tsp, pathp, dgcdp); if (failed) { db_free_tree(curtree, tsp->ts_resp); return (union tree *)NULL; } } else if (curtree->tr_op != OP_NMG_TESS) { bu_vls_printf(dgcdp->gedp->ged_result_str, "Cannot use '-d' option when Boolean evaluation is required\n"); db_free_tree(curtree, tsp->ts_resp); return (union tree *)NULL; } r = curtree->tr_d.td_r; NMG_CK_REGION(r); if (dgcdp->do_not_draw_nmg_solids_during_debugging && r) { db_free_tree(curtree, tsp->ts_resp); return (union tree *)NULL; } if (dgcdp->nmg_triangulate) { failed = process_triangulation(tsp, pathp, dgcdp); if (failed) { db_free_tree(curtree, tsp->ts_resp); return (union tree *)NULL; } } if (r != 0) { int style; /* Convert NMG to vlist */ NMG_CK_REGION(r); if (dgcdp->draw_wireframes) { /* Draw in vector form */ style = NMG_VLIST_STYLE_VECTOR; } else { /* Default -- draw polygons */ style = NMG_VLIST_STYLE_POLYGON; } if (dgcdp->draw_normals) { style |= NMG_VLIST_STYLE_VISUALIZE_NORMALS; } if (dgcdp->shade_per_vertex_normals) { style |= NMG_VLIST_STYLE_USE_VU_NORMALS; } if (dgcdp->draw_no_surfaces) { style |= NMG_VLIST_STYLE_NO_SURFACES; } nmg_r_to_vlist(&vhead, r, style); _ged_drawH_part2(0, &vhead, pathp, tsp, dgcdp); if (dgcdp->draw_edge_uses) { nmg_vlblock_r(dgcdp->draw_edge_uses_vbp, r, 1); } /* NMG region is no longer necessary, only vlist remains */ db_free_tree(curtree, tsp->ts_resp); return (union tree *)NULL; } /* Return tree -- it needs to be freed (by caller) */ return curtree; }
int ged_put_comb(struct ged *gedp, int argc, const char *argv[]) { struct directory *dp; struct rt_db_internal intern; struct rt_comb_internal *comb; char new_name_v4[NAMESIZE+1]; char *new_name; int offset; int save_comb_flag = 0; static const char *usage = "comb_name is_Region id air material los color shader inherit boolean_expr"; static const char *noregionusage = "comb_name n color shader inherit boolean_expr"; static const char *regionusage = "comb_name y id air material los color shader inherit boolean_expr"; const char *saved_name = NULL; GED_CHECK_DATABASE_OPEN(gedp, GED_ERROR); GED_CHECK_READ_ONLY(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 < 7 || 11 < argc) { bu_vls_printf(gedp->ged_result_str, "Usage: %s %s", argv[0], usage); return GED_ERROR; } comb = (struct rt_comb_internal *)NULL; dp = db_lookup(gedp->ged_wdbp->dbip, argv[1], LOOKUP_QUIET); if (dp != RT_DIR_NULL) { if (!(dp->d_flags & RT_DIR_COMB)) { bu_vls_printf(gedp->ged_result_str, "%s: %s is not a combination, so cannot be edited this way\n", argv[0], argv[1]); return GED_ERROR; } if (rt_db_get_internal(&intern, dp, gedp->ged_wdbp->dbip, (fastf_t *)NULL, &rt_uniresource) < 0) { bu_vls_printf(gedp->ged_result_str, "%s: Database read error, aborting\n", argv[0]); return GED_ERROR; } comb = (struct rt_comb_internal *)intern.idb_ptr; saved_name = save_comb(gedp, dp); /* Save combination to a temp name */ save_comb_flag = 1; } /* empty the existing combination */ if (comb) { db_free_tree(comb->tree, &rt_uniresource); comb->tree = NULL; } else { /* make an empty combination structure */ BU_ALLOC(comb, struct rt_comb_internal); if (comb == NULL) bu_bomb("Unable to allocate comb memory"); RT_COMB_INTERNAL_INIT(comb); } if (db_version(gedp->ged_wdbp->dbip) < 5) { new_name = new_name_v4; if (dp == RT_DIR_NULL) NAMEMOVE(argv[1], new_name_v4); else NAMEMOVE(dp->d_namep, new_name_v4); } else { if (dp == RT_DIR_NULL) new_name = (char *)argv[1]; else new_name = dp->d_namep; } if (*argv[2] == 'y' || *argv[2] == 'Y') comb->region_flag = 1; else comb->region_flag = 0; if (comb->region_flag) { if (argc != 11) { bu_vls_printf(gedp->ged_result_str, "region_flag is set, incorrect number of arguments supplied.\n"); bu_vls_printf(gedp->ged_result_str, "Usage: %s %s", argv[0], regionusage); return GED_ERROR; } comb->region_id = atoi(argv[3]); comb->aircode = atoi(argv[4]); comb->GIFTmater = atoi(argv[5]); comb->los = atoi(argv[6]); offset = 6; } else { if (argc != 7) { bu_vls_printf(gedp->ged_result_str, "region_flag is not set, incorrect number of arguments supplied.\n"); bu_vls_printf(gedp->ged_result_str, "Usage: %s %s", argv[0], noregionusage); return GED_ERROR; } offset = 2; } put_rgb_into_comb(comb, argv[offset + 1]); bu_vls_strcpy(&comb->shader, argv[offset +2]); if (*argv[offset + 3] == 'y' || *argv[offset + 3] == 'Y') comb->inherit = 1; else comb->inherit = 0; if (put_tree_into_comb(gedp, comb, dp, argv[1], new_name, argv[offset + 4]) == GED_ERROR) { if (comb && dp) { restore_comb(gedp, dp, saved_name); bu_vls_printf(gedp->ged_result_str, "%s: \toriginal restored\n", argv[0]); } bu_file_delete(_ged_tmpfil); return GED_ERROR; } else if (save_comb_flag) { /* eliminate the temporary combination */ const char *av[3]; av[0] = "kill"; av[1] = saved_name; av[2] = NULL; (void)ged_kill(gedp, 2, (const char **)av); } bu_file_delete(_ged_tmpfil); return GED_OK; }
int wdb_comb_std_cmd(struct rt_wdb *wdbp, Tcl_Interp *interp, int argc, char **argv) { char *comb_name; int ch; int region_flag = -1; register struct directory *dp; struct rt_db_internal intern; struct rt_comb_internal *comb = NULL; struct tokens tok_hd; struct tokens *tok; short last_tok; int i; union tree *final_tree; if (wdbp->dbip->dbi_read_only) { Tcl_AppendResult(interp, "Database is read-only!\n", (char *)NULL); return TCL_ERROR; } if (argc < 3 || RT_MAXARGS < argc) { struct bu_vls vls; bu_vls_init(&vls); bu_vls_printf(&vls, "helplib_alias wdb_comb_std %s", argv[0]); Tcl_Eval(interp, bu_vls_addr(&vls)); bu_vls_free(&vls); return TCL_ERROR; } /* Parse options */ bu_optind = 1; /* re-init bu_getopt() */ while ((ch = bu_getopt(argc, argv, "cgr?")) != EOF) { switch (ch) { case 'c': case 'g': region_flag = 0; break; case 'r': region_flag = 1; break; /* XXX How about -p and -v for FASTGEN? */ case '?': default: PRINT_USAGE; return TCL_OK; } } argc -= (bu_optind + 1); argv += bu_optind; comb_name = *argv++; if (argc == -1) { PRINT_USAGE; return TCL_OK; } if ((region_flag != -1) && (argc == 0)) { /* * Set/Reset the REGION flag of an existing combination */ if ((dp = db_lookup(wdbp->dbip, comb_name, LOOKUP_NOISY)) == DIR_NULL) return TCL_ERROR; if (!(dp->d_flags & DIR_COMB)) { Tcl_AppendResult(interp, comb_name, " is not a combination\n", (char *)0 ); return TCL_ERROR; } if (rt_db_get_internal(&intern, dp, wdbp->dbip, (fastf_t *)NULL, &rt_uniresource) < 0) { Tcl_AppendResult(interp, "Database read error, aborting\n", (char *)NULL); return TCL_ERROR; } comb = (struct rt_comb_internal *)intern.idb_ptr; RT_CK_COMB(comb); if (region_flag) { if ( !comb->region_flag ) { /* assign values from the defaults */ comb->region_id = wdbp->wdb_item_default++; comb->aircode = wdbp->wdb_air_default; comb->GIFTmater = wdbp->wdb_mat_default; comb->los = wdbp->wdb_los_default; } comb->region_flag = 1; } else comb->region_flag = 0; if (rt_db_put_internal(dp, wdbp->dbip, &intern, &rt_uniresource) < 0) { rt_db_free_internal(&intern, &rt_uniresource); Tcl_AppendResult(interp, "Database write error, aborting\n", (char *)NULL); return TCL_ERROR; } return TCL_OK; } /* * At this point, we know we have a Boolean expression. * If the combination already existed and region_flag is -1, * then leave its region_flag alone. * If the combination didn't exist yet, * then pretend region_flag was 0. * Otherwise, make sure to set its c_flags according to region_flag. */ dp = db_lookup( wdbp->dbip, comb_name, LOOKUP_QUIET ); if (dp != DIR_NULL) { Tcl_AppendResult(interp, "ERROR: ", comb_name, " already exists\n", (char *)0 ); return TCL_ERROR; } /* parse Boolean expression */ BU_LIST_INIT(&tok_hd.l); tok_hd.type = WDB_TOK_NULL; last_tok = WDB_TOK_LPAREN; for (i=0; i<argc; i++) { char *ptr; ptr = argv[i]; while (*ptr) { while (*ptr == '(' || *ptr == ')') { switch (*ptr) { case '(': wdb_append_lparen( &tok_hd.l ); last_tok = WDB_TOK_LPAREN; break; case ')': wdb_append_rparen( &tok_hd.l ); last_tok = WDB_TOK_RPAREN; break; } ptr++; } if (*ptr == '\0') continue; if (last_tok == WDB_TOK_RPAREN) { /* next token MUST be an operator */ if (wdb_add_operator(interp, &tok_hd.l, *ptr, &last_tok) == TCL_ERROR) { wdb_free_tokens(&tok_hd.l); if (dp != DIR_NULL) rt_db_free_internal(&intern, &rt_uniresource); return TCL_ERROR; } ptr++; } else if (last_tok == WDB_TOK_LPAREN) { /* next token MUST be an operand */ int name_len; name_len = wdb_add_operand(interp, &tok_hd.l, ptr ); if (name_len < 1) { wdb_free_tokens(&tok_hd.l); if (dp != DIR_NULL) rt_db_free_internal(&intern, &rt_uniresource); return TCL_ERROR; } last_tok = WDB_TOK_TREE; ptr += name_len; } else if (last_tok == WDB_TOK_TREE) { /* must be an operator */ if (wdb_add_operator(interp, &tok_hd.l, *ptr, &last_tok) == TCL_ERROR) { wdb_free_tokens(&tok_hd.l); if (dp != DIR_NULL) rt_db_free_internal(&intern, &rt_uniresource); return TCL_ERROR; } ptr++; } else if (last_tok == WDB_TOK_UNION || last_tok == WDB_TOK_INTER || last_tok == WDB_TOK_SUBTR) { /* must be an operand */ int name_len; name_len = wdb_add_operand(interp, &tok_hd.l, ptr ); if (name_len < 1) { wdb_free_tokens(&tok_hd.l); if (dp != DIR_NULL) rt_db_free_internal(&intern, &rt_uniresource); return TCL_ERROR; } last_tok = WDB_TOK_TREE; ptr += name_len; } } } if (wdb_check_syntax(interp, wdbp->dbip, &tok_hd.l, comb_name, dp)) { wdb_free_tokens(&tok_hd.l); return TCL_ERROR; } /* replace any occurences of comb_name with existing tree */ if (dp != DIR_NULL) { for (BU_LIST_FOR(tok, tokens, &tok_hd.l)) { struct rt_db_internal intern1; struct rt_comb_internal *comb1; switch (tok->type) { case WDB_TOK_LPAREN: case WDB_TOK_RPAREN: case WDB_TOK_UNION: case WDB_TOK_INTER: case WDB_TOK_SUBTR: break; case WDB_TOK_TREE: if (!strcmp(tok->tp->tr_l.tl_name, comb_name)) { db_free_tree( tok->tp, &rt_uniresource ); if (rt_db_get_internal(&intern1, dp, wdbp->dbip, (fastf_t *)NULL, &rt_uniresource) < 0) { Tcl_AppendResult(interp, "Cannot get records for ", comb_name, "\n", (char *)NULL); Tcl_AppendResult(interp, "Database read error, aborting\n", (char *)NULL); return TCL_ERROR; } comb1 = (struct rt_comb_internal *)intern1.idb_ptr; RT_CK_COMB(comb1); tok->tp = comb1->tree; comb1->tree = (union tree *)NULL; rt_db_free_internal(&intern1, &rt_uniresource); } break; default: Tcl_AppendResult(interp, "ERROR: Unrecognized token type\n", (char *)NULL); wdb_free_tokens(&tok_hd.l); return TCL_ERROR; } } } final_tree = wdb_eval_bool(&tok_hd.l); if (dp == DIR_NULL) { int flags; flags = DIR_COMB; BU_GETSTRUCT(comb, rt_comb_internal); comb->magic = RT_COMB_MAGIC; comb->tree = final_tree; bu_vls_init(&comb->shader); bu_vls_init(&comb->material); comb->region_id = -1; if (region_flag == (-1)) comb->region_flag = 0; else comb->region_flag = region_flag; if (comb->region_flag) { struct bu_vls tmp_vls; comb->region_flag = 1; comb->region_id = wdbp->wdb_item_default++;; comb->aircode = wdbp->wdb_air_default; comb->los = wdbp->wdb_los_default; comb->GIFTmater = wdbp->wdb_mat_default; bu_vls_init(&tmp_vls); bu_vls_printf(&tmp_vls, "Creating region id=%d, air=%d, los=%d, GIFTmaterial=%d\n", comb->region_id, comb->aircode, comb->los, comb->GIFTmater); Tcl_AppendResult(interp, bu_vls_addr(&tmp_vls), (char *)NULL); bu_vls_free(&tmp_vls); flags |= DIR_REGION; } RT_INIT_DB_INTERNAL(&intern); intern.idb_major_type = DB5_MAJORTYPE_BRLCAD; intern.idb_type = ID_COMBINATION; intern.idb_meth = &rt_functab[ID_COMBINATION]; intern.idb_ptr = (genptr_t)comb; if ((dp=db_diradd(wdbp->dbip, comb_name, -1L, 0, flags, (genptr_t)&intern.idb_type)) == DIR_NULL) { Tcl_AppendResult(interp, "Failed to add ", comb_name, " to directory, aborting\n", (char *)NULL); return TCL_ERROR; } if (rt_db_put_internal(dp, wdbp->dbip, &intern, &rt_uniresource) < 0) { Tcl_AppendResult(interp, "Failed to write ", dp->d_namep, (char *)NULL ); return TCL_ERROR; } } else { db_delete(wdbp->dbip, dp); dp->d_len = 0; dp->d_un.file_offset = -1; db_free_tree(comb->tree, &rt_uniresource); comb->tree = final_tree; if (rt_db_put_internal(dp, wdbp->dbip, &intern, &rt_uniresource) < 0) { Tcl_AppendResult(interp, "Failed to write ", dp->d_namep, (char *)NULL ); return TCL_ERROR; } } return TCL_OK; }
int ged_facetize(struct ged *gedp, int argc, const char *argv[]) { int i; int c; char *newname; struct rt_db_internal intern; struct directory *dp; int failed; int nmg_use_tnurbs = 0; struct db_tree_state init_state; struct db_i *dbip; union tree *facetize_tree; struct model *nmg_model; static const char *usage = "[ [-P] | [-n] [-t] [-T] ] new_obj old_obj [old_obj2 old_obj3 ...]"; /* static due to jumping */ static int triangulate; static int make_bot; static int marching_cube; static int screened_poisson; GED_CHECK_DATABASE_OPEN(gedp, GED_ERROR); GED_CHECK_READ_ONLY(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) { bu_vls_printf(gedp->ged_result_str, "Usage: %s %s", argv[0], usage); return GED_ERROR; } dbip = gedp->ged_wdbp->dbip; RT_CHECK_DBI(dbip); db_init_db_tree_state(&init_state, dbip, gedp->ged_wdbp->wdb_resp); /* Establish tolerances */ init_state.ts_ttol = &gedp->ged_wdbp->wdb_ttol; init_state.ts_tol = &gedp->ged_wdbp->wdb_tol; /* Initial values for options, must be reset each time */ marching_cube = 0; screened_poisson = 0; triangulate = 0; make_bot = 1; /* Parse options. */ bu_optind = 1; /* re-init bu_getopt() */ while ((c=bu_getopt(argc, (char * const *)argv, "mntTP")) != -1) { switch (c) { case 'm': marching_cube = triangulate = 1; /* no break, marching cubes assumes nmg for now */ case 'n': make_bot = 0; break; case 'P': screened_poisson = 1; triangulate = 1; make_bot = 1; break; case 'T': triangulate = 1; break; case 't': nmg_use_tnurbs = 1; break; default: { bu_vls_printf(gedp->ged_result_str, "Usage: %s %s", argv[0], usage); return GED_ERROR; } } } argc -= bu_optind; argv += bu_optind; if (argc < 0) { bu_vls_printf(gedp->ged_result_str, "facetize: missing argument\n"); return GED_ERROR; } if (screened_poisson && (marching_cube || !make_bot || nmg_use_tnurbs)) { bu_vls_printf(gedp->ged_result_str, "Usage: %s %s", argv[0], usage); return GED_ERROR; } newname = (char *)argv[0]; argv++; argc--; if (argc < 0) { bu_vls_printf(gedp->ged_result_str, "facetize: missing argument\n"); return GED_ERROR; } if (db_lookup(dbip, newname, LOOKUP_QUIET) != RT_DIR_NULL) { bu_vls_printf(gedp->ged_result_str, "error: solid '%s' already exists, aborting\n", newname); return GED_ERROR; } if (screened_poisson) { struct rt_bot_internal *bot; BU_ALLOC(bot, struct rt_bot_internal); bot->magic = RT_BOT_INTERNAL_MAGIC; bot->mode = RT_BOT_SOLID; bot->orientation = RT_BOT_UNORIENTED; bot->thickness = (fastf_t *)NULL; bot->face_mode = (struct bu_bitv *)NULL; /* TODO - generate point cloud, then mesh - need to see the input points for debugging */ (void)rt_generate_mesh(&(bot->faces), (int *)&(bot->num_faces), (point_t **)&(bot->vertices), (int *)&(bot->num_vertices), dbip, argv[0], 15); /* Export BOT as a new solid */ RT_DB_INTERNAL_INIT(&intern); intern.idb_major_type = DB5_MAJORTYPE_BRLCAD; intern.idb_type = ID_BOT; intern.idb_meth = &OBJ[ID_BOT]; intern.idb_ptr = (void *) bot; } else { bu_vls_printf(gedp->ged_result_str, "facetize: tessellating primitives with tolerances a=%g, r=%g, n=%g\n", gedp->ged_wdbp->wdb_ttol.abs, gedp->ged_wdbp->wdb_ttol.rel, gedp->ged_wdbp->wdb_ttol.norm); facetize_tree = (union tree *)0; nmg_model = nmg_mm(); init_state.ts_m = &nmg_model; i = db_walk_tree(dbip, argc, (const char **)argv, 1, &init_state, 0, /* take all regions */ facetize_region_end, nmg_use_tnurbs ? nmg_booltree_leaf_tnurb : nmg_booltree_leaf_tess, (void *)&facetize_tree ); if (i < 0) { bu_vls_printf(gedp->ged_result_str, "facetize: error in db_walk_tree()\n"); /* Destroy NMG */ nmg_km(nmg_model); return GED_ERROR; } if (facetize_tree) { /* Now, evaluate the boolean tree into ONE region */ bu_vls_printf(gedp->ged_result_str, "facetize: evaluating boolean expressions\n"); if (!BU_SETJUMP) { /* try */ failed = nmg_boolean(facetize_tree, nmg_model, &gedp->ged_wdbp->wdb_tol, &rt_uniresource); } else { /* catch */ BU_UNSETJUMP; bu_vls_printf(gedp->ged_result_str, "WARNING: facetization failed!!!\n"); db_free_tree(facetize_tree, &rt_uniresource); facetize_tree = (union tree *)NULL; nmg_km(nmg_model); nmg_model = (struct model *)NULL; return GED_ERROR; } BU_UNSETJUMP; } else failed = 1; if (failed) { bu_vls_printf(gedp->ged_result_str, "facetize: no resulting region, aborting\n"); db_free_tree(facetize_tree, &rt_uniresource); facetize_tree = (union tree *)NULL; nmg_km(nmg_model); nmg_model = (struct model *)NULL; return GED_ERROR; } /* New region remains part of this nmg "model" */ NMG_CK_REGION(facetize_tree->tr_d.td_r); bu_vls_printf(gedp->ged_result_str, "facetize: %s\n", facetize_tree->tr_d.td_name); /* Triangulate model, if requested */ if (triangulate && !make_bot) { bu_vls_printf(gedp->ged_result_str, "facetize: triangulating resulting object\n"); if (!BU_SETJUMP) { /* try */ if (marching_cube == 1) nmg_triangulate_model_mc(nmg_model, &gedp->ged_wdbp->wdb_tol); else nmg_triangulate_model(nmg_model, &gedp->ged_wdbp->wdb_tol); } else { /* catch */ BU_UNSETJUMP; bu_vls_printf(gedp->ged_result_str, "WARNING: triangulation failed!!!\n"); db_free_tree(facetize_tree, &rt_uniresource); facetize_tree = (union tree *)NULL; nmg_km(nmg_model); nmg_model = (struct model *)NULL; return GED_ERROR; } BU_UNSETJUMP; } if (make_bot) { struct rt_bot_internal *bot; struct nmgregion *r; struct shell *s; bu_vls_printf(gedp->ged_result_str, "facetize: converting to BOT format\n"); /* WTF, FIXME: this is only dumping the first shell of the first region */ r = BU_LIST_FIRST(nmgregion, &nmg_model->r_hd); if (r && BU_LIST_NEXT(nmgregion, &r->l) != (struct nmgregion *)&nmg_model->r_hd) bu_vls_printf(gedp->ged_result_str, "WARNING: model has more than one region, only facetizing the first\n"); s = BU_LIST_FIRST(shell, &r->s_hd); if (s && BU_LIST_NEXT(shell, &s->l) != (struct shell *)&r->s_hd) bu_vls_printf(gedp->ged_result_str, "WARNING: model has more than one shell, only facetizing the first\n"); if (!BU_SETJUMP) { /* try */ bot = (struct rt_bot_internal *)nmg_bot(s, &gedp->ged_wdbp->wdb_tol); } else { /* catch */ BU_UNSETJUMP; bu_vls_printf(gedp->ged_result_str, "WARNING: conversion to BOT failed!\n"); db_free_tree(facetize_tree, &rt_uniresource); facetize_tree = (union tree *)NULL; nmg_km(nmg_model); nmg_model = (struct model *)NULL; return GED_ERROR; } BU_UNSETJUMP; nmg_km(nmg_model); nmg_model = (struct model *)NULL; /* Export BOT as a new solid */ RT_DB_INTERNAL_INIT(&intern); intern.idb_major_type = DB5_MAJORTYPE_BRLCAD; intern.idb_type = ID_BOT; intern.idb_meth = &OBJ[ID_BOT]; intern.idb_ptr = (void *) bot; } else { bu_vls_printf(gedp->ged_result_str, "facetize: converting NMG to database format\n"); /* Export NMG as a new solid */ RT_DB_INTERNAL_INIT(&intern); intern.idb_major_type = DB5_MAJORTYPE_BRLCAD; intern.idb_type = ID_NMG; intern.idb_meth = &OBJ[ID_NMG]; intern.idb_ptr = (void *)nmg_model; nmg_model = (struct model *)NULL; } } dp=db_diradd(dbip, newname, RT_DIR_PHONY_ADDR, 0, RT_DIR_SOLID, (void *)&intern.idb_type); if (dp == RT_DIR_NULL) { bu_vls_printf(gedp->ged_result_str, "Cannot add %s to directory\n", newname); return GED_ERROR; } if (rt_db_put_internal(dp, dbip, &intern, &rt_uniresource) < 0) { bu_vls_printf(gedp->ged_result_str, "Failed to write %s to database\n", newname); rt_db_free_internal(&intern); return GED_ERROR; } if (!screened_poisson) { facetize_tree->tr_d.td_r = (struct nmgregion *)NULL; /* Free boolean tree, and the regions in it */ db_free_tree(facetize_tree, &rt_uniresource); facetize_tree = (union tree *)NULL; } return GED_OK; }