/* * Convert a UPenn Jack data base into a BRL-CAD data base. */ void jack_to_brlcad(FILE *fpin, struct rt_wdb *fpout, char *reg_name, char *grp_name, char *jfile) { struct model *m; m = nmg_mm(); /* Make nmg model. */ psurf_to_nmg(m, fpin, jfile); /* Convert psurf model to nmg. */ create_brlcad_db(fpout, m, reg_name, grp_name); /* Put in db. */ nmg_km(m); /* Destroy the nmg model. */ }
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; } }
int off2nmg(FILE *fpin, struct rt_wdb *fpout) { char title[64], geom_fname[64]; char rname[67], sname[67]; char buf[200], buf2[200]; FILE *fgeom; struct model *m; title[0] = geom_fname[0] = '\0'; bu_fgets(buf, sizeof(buf), fpin); while (!feof(fpin)) { /* Retrieve the important data */ if (sscanf(buf, "name %[^\n]s", buf2) > 0) bu_strlcpy(title, buf2, sizeof(title)); if (sscanf(buf, "geometry %200[^\n]s", buf2) > 0) { char dtype[40], format[40]; if (sscanf(buf2, "%40s %40s %64s", dtype, format, geom_fname) != 3) bu_exit(1, "Incomplete geometry field in input file."); if (!BU_STR_EQUAL(dtype, "indexed_poly")) bu_exit(1, "Unknown geometry data type. Must be \"indexed_poly\"."); } bu_fgets(buf, sizeof(buf), fpin); } if (strlen(title) < (unsigned)1) fprintf(stderr, "Warning: no title\n"); if (strlen(geom_fname) < (unsigned)1) bu_exit(1, "ERROR: no geometry filename given"); if ((fgeom = fopen(geom_fname, "rb")) == NULL) { bu_exit(1, "off2nmg: cannot open %s (geometry description) for reading\n", geom_fname); } m = nmg_mm(); read_faces(m, fgeom); fclose(fgeom); snprintf(sname, 67, "s.%s", title); snprintf(rname, 67, "r.%s", title); mk_id(fpout, title); mk_nmg(fpout, sname, m); mk_comb1(fpout, rname, sname, 1); nmg_km(m); return 0; }
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; }
static void process_triangulation(struct nmgregion *r, const struct db_full_path *pathp, struct db_tree_state *tsp) { if (!BU_SETJUMP) { /* try */ /* Write the facetized region to the output file */ output_nmg(r, pathp, tsp->ts_regionid, tsp->ts_gmater); } else { /* catch */ char *sofar; sofar = db_path_to_string(pathp); bu_log("FAILED in triangulator: %s\n", sofar); 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(); } BU_UNSETJUMP; }
int extrude(int entityno) { fastf_t length; /* extrusion length */ vect_t edir; /* a unit vector (direction of extrusion */ vect_t evect; /* Scaled vector for extrusion */ int sol_num; /* IGES solid type number */ int curve; /* pointer to directory entry for base curve */ struct ptlist *curv_pts; /* List of points along curve */ int i; /* Default values */ VSET(edir, 0.0, 0.0, 1.0); /* 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, ""); /* Read pointer to directory entry for curve to be extruded */ Readint(&curve, ""); /* Convert this to a "dir" index */ curve = (curve-1)/2; Readcnv(&length, ""); Readflt(&edir[X], ""); Readflt(&edir[Y], ""); Readflt(&edir[Z], ""); if (length <= 0.0) { bu_log("Illegal parameters for entity D%07d (%s)\n" , dir[entityno]->direct, dir[entityno]->name); return 0; } /* * Unitize direction vector */ VUNITIZE(edir); /* Scale vector */ VSCALE(evect, edir, length); /* Switch based on type of curve to be extruded */ switch (dir[curve]->type) { case 100: /* circular arc */ return Extrudcirc(entityno, curve, evect); case 104: /* conic arc */ return Extrudcon(entityno, curve, evect); case 102: /* composite curve */ case 106: /* copius data */ case 112: /* parametric spline */ case 126: { /* B-spline */ int npts; struct model *m; struct nmgregion *r; struct shell *s; struct faceuse *fu; struct loopuse *lu; struct edgeuse *eu; struct ptlist *pt_ptr; npts = Getcurve(curve, &curv_pts); if (npts < 3) return 0; m = nmg_mm(); r = nmg_mrsv(m); s = BU_LIST_FIRST(shell, &r->s_hd); fu = nmg_cface(s, (struct vertex **)NULL, npts-1); pt_ptr = curv_pts; lu = BU_LIST_FIRST(loopuse, &fu->lu_hd); for (BU_LIST_FOR(eu, edgeuse, &lu->down_hd)) { struct vertex *v; v = eu->vu_p->v_p; nmg_vertex_gv(v, pt_ptr->pt); pt_ptr = pt_ptr->next; } if (nmg_calc_face_g(fu)) { bu_log("Extrude: Failed to calculate face geometry\n"); nmg_km(m); bu_free((char *)curv_pts, "curve_pts"); return 0; } if (nmg_extrude_face(fu, evect, &tol)) { bu_log("Extrude: extrusion failed\n"); nmg_km(m); bu_free((char *)curv_pts, "curve_pts"); return 0; } mk_bot_from_nmg(fdout, dir[entityno]->name, s); nmg_km(m); bu_free((char *)curv_pts, "curve_pts"); return 1; } default: i = (-1); while (dir[curve]->type != typecount[++i].type && i < ntypes); bu_log("Extrusions of %s are not allowed\n", typecount[i].name); break; } return 0; }
static int gcv_vrml_write(const char *path, struct db_i *vdbip, const struct gcv_opts *UNUSED(options)) { size_t i; struct plate_mode pm; size_t num_objects = 0; char **object_names = NULL; out_file = path; dbip = vdbip; bu_setlinebuf(stderr); the_model = nmg_mm(); tree_state = rt_initial_tree_state; /* struct copy */ tree_state.ts_tol = &tol; tree_state.ts_ttol = &ttol; tree_state.ts_m = &the_model; ttol.magic = RT_TESS_TOL_MAGIC; /* Defaults, updated by command line options. */ ttol.abs = 0.0; ttol.rel = 0.01; ttol.norm = 0.0; tol.magic = BN_TOL_MAGIC; tol.dist = 0.005; tol.dist_sq = tol.dist * tol.dist; tol.perp = 1e-6; tol.para = 1 - tol.perp; /* NOTE: For visualization purposes, in the debug plot files */ { /* WTF: This value is specific to the Bradley */ nmg_eue_dist = 2.0; } BU_LIST_INIT(&RTG.rtg_vlfree); /* for vlist macros */ if ((bot_dump == 1) && (eval_all == 1)) { bu_log("BOT Dump and Evaluate All are mutually exclusive\n"); return 0; } if (out_file == NULL) { fp_out = stdout; setmode(fileno(fp_out), O_BINARY); } else { if ((fp_out = fopen(out_file, "wb")) == NULL) { perror("g-vrml"); bu_log("Cannot open %s\n", out_file); return 0; } } fprintf(fp_out, "#VRML V2.0 utf8\n"); fprintf(fp_out, "#Units are %s\n", units); /* NOTE: We may want to inquire about bounding boxes for the * various groups and add Viewpoints nodes that point the camera * to the center and orient for Top, Side, etc. Views. We will add * some default Material Color definitions (for thousands groups) * before we start defining the geometry. */ fprintf(fp_out, "Shape { appearance Appearance { material DEF Material_999 Material { diffuseColor 0.78 0.78 0.78 } } }\n"); fprintf(fp_out, "Shape { appearance Appearance { material DEF Material_1999 Material { diffuseColor 0.88 0.29 0.29 } } }\n"); fprintf(fp_out, "Shape { appearance Appearance { material DEF Material_2999 Material { diffuseColor 0.82 0.53 0.54 } } }\n"); fprintf(fp_out, "Shape { appearance Appearance { material DEF Material_3999 Material { diffuseColor 0.39 0.89 0.00 } } }\n"); fprintf(fp_out, "Shape { appearance Appearance { material DEF Material_4999 Material { diffuseColor 1.00 0.00 0.00 } } }\n"); fprintf(fp_out, "Shape { appearance Appearance { material DEF Material_5999 Material { diffuseColor 0.82 0.00 0.82 } } }\n"); fprintf(fp_out, "Shape { appearance Appearance { material DEF Material_6999 Material { diffuseColor 0.62 0.62 0.62 } } }\n"); fprintf(fp_out, "Shape { appearance Appearance { material DEF Material_7999 Material { diffuseColor 0.49 0.49 0.49 } } }\n"); fprintf(fp_out, "Shape { appearance Appearance { material DEF Material_8999 Material { diffuseColor 0.18 0.31 0.31 } } }\n"); fprintf(fp_out, "Shape { appearance Appearance { material DEF Material_9999 Material { diffuseColor 0.00 0.41 0.82 } } }\n"); /* I had hoped to create a separate sub-tree (using the Transform * node) for each group name argument however, it appears they are * all handled at the same time so I will only have one Transform * for the complete conversion. Later on switch nodes may be added * to turn on and off the groups (via ROUTE nodes). */ fprintf(fp_out, "Transform {\n"); fprintf(fp_out, "\tchildren [\n"); pm.num_bots = 0; pm.num_nonbots = 0; if (!eval_all) { pm.array_size = 5; pm.bots = (struct rt_bot_internal **)bu_calloc(pm.array_size, sizeof(struct rt_bot_internal *), "pm.bots"); } /* get toplevel objects */ { struct directory **results; db_update_nref(dbip, &rt_uniresource); num_objects = db_ls(dbip, DB_LS_TOPS, NULL, &results); object_names = db_dpv_to_argv(results); bu_free(results, "tops"); } if (eval_all) { (void)db_walk_tree(dbip, num_objects, (const char **)(object_names), 1, /* ncpu */ &tree_state, 0, nmg_region_end, nmg_booltree_leaf_tess, (void *)&pm); /* in librt/nmg_bool.c */ goto out; } if (bot_dump) { (void)db_walk_tree(dbip, num_objects, (const char **)(object_names), 1, /* ncpu */ &tree_state, 0, do_region_end2, leaf_tess2, (void *)&pm); /* in librt/nmg_bool.c */ goto out; } for (i = 0; i < num_objects; i++) { struct directory *dp; dp = db_lookup(dbip, object_names[i], LOOKUP_QUIET); if (dp == RT_DIR_NULL) { bu_log("Cannot find %s\n", object_names[i]); continue; } /* light source must be a combination */ if (!(dp->d_flags & RT_DIR_COMB)) { continue; } fprintf(fp_out, "# Includes group %s\n", object_names[i]); /* walk trees selecting only light source regions */ (void)db_walk_tree(dbip, 1, (const char **)(&object_names[i]), 1, /* ncpu */ &tree_state, select_lights, do_region_end1, leaf_tess1, (void *)&pm); /* in librt/nmg_bool.c */ } /* Walk indicated tree(s). Each non-light-source region will be output separately */ (void)db_walk_tree(dbip, num_objects, (const char **)(object_names), 1, /* ncpu */ &tree_state, select_non_lights, do_region_end1, leaf_tess1, (void *)&pm); /* in librt/nmg_bool.c */ /* Release dynamic storage */ nmg_km(the_model); if (!eval_all) { bu_free(pm.bots, "pm.bots"); } out: bu_free(object_names, "object_names"); /* Now we need to close each group set */ fprintf(fp_out, "\t]\n}\n"); bu_log("\nTotal of %d regions converted of %d regions attempted.\n", regions_converted, regions_tried); if (regions_converted != regions_tried) { bu_log("Of the %d which failed conversion, %d of these failed due to conversion error.\n", regions_tried - regions_converted, bomb_cnt); } fclose(fp_out); bu_log("Done.\n"); return 1; }
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; }
/* * M A I N */ int main(int argc, char **argv) { register int c; double percent; bu_setlinebuf( stderr ); #if MEMORY_LEAK_CHECKING rt_g.debug |= DEBUG_MEM_FULL; #endif tree_state = rt_initial_tree_state; /* struct copy */ tree_state.ts_tol = &tol; tree_state.ts_ttol = &ttol; tree_state.ts_m = &the_model; ttol.magic = RT_TESS_TOL_MAGIC; /* Defaults, updated by command line options. */ ttol.abs = 0.0; ttol.rel = 0.01; ttol.norm = 0.0; /* XXX These need to be improved */ tol.magic = BN_TOL_MAGIC; tol.dist = 0.005; tol.dist_sq = tol.dist * tol.dist; tol.perp = 1e-5; tol.para = 1 - tol.perp; rt_init_resource( &rt_uniresource, 0, NULL ); the_model = nmg_mm(); BU_LIST_INIT( &rt_g.rtg_vlfree ); /* for vlist macros */ /* Get command line arguments. */ while ((c = bu_getopt(argc, argv, "mua:n:o:r:vx:D:P:X:e:i")) != EOF) { switch (c) { case 'm': /* include 'usemtl' statements */ usemtl = 1; break; case 'u': /* Include vertexuse normals */ do_normals = 1; break; case 'a': /* Absolute tolerance. */ ttol.abs = atof(bu_optarg); ttol.rel = 0.0; break; case 'n': /* Surface normal tolerance. */ ttol.norm = atof(bu_optarg); ttol.rel = 0.0; break; case 'o': /* Output file name. */ output_file = bu_optarg; break; case 'r': /* Relative tolerance. */ ttol.rel = atof(bu_optarg); break; case 'v': verbose++; break; case 'P': ncpu = atoi( bu_optarg ); rt_g.debug = 1; /* XXX DEBUG_ALLRAYS -- to get core dumps */ break; case 'x': sscanf( bu_optarg, "%x", (unsigned int *)&rt_g.debug ); break; case 'D': tol.dist = atof(bu_optarg); tol.dist_sq = tol.dist * tol.dist; rt_pr_tol( &tol ); break; case 'X': sscanf( bu_optarg, "%x", (unsigned int *)&rt_g.NMG_debug ); NMG_debug = rt_g.NMG_debug; break; case 'e': /* Error file name. */ error_file = bu_optarg; break; case 'i': inches = 1; break; default: bu_exit(1, usage, argv[0]); break; } } if (bu_optind+1 >= argc) { bu_exit(1, usage, argv[0]); } if ( !output_file ) fp = stdout; else { /* Open output file */ if ( (fp=fopen( output_file, "wb+" )) == NULL ) { perror( argv[0] ); bu_exit(1, "Cannot open output file (%s) for writing\n", output_file ); } } /* Open g-obj error log file */ if (!error_file) { fpe = stderr; #if defined(_WIN32) && !defined(__CYGWIN__) setmode(fileno(fpe), O_BINARY); #endif } else if ((fpe=fopen(error_file, "wb")) == NULL) { perror( argv[0] ); bu_exit(1, "Cannot open output file (%s) for writing\n", error_file ); } /* Open BRL-CAD database */ argc -= bu_optind; argv += bu_optind; if ((dbip = db_open(argv[0], "r")) == DBI_NULL) { perror(argv[0]); bu_exit(1, "Unable to open geometry file (%s) for reading\n", argv[0]); } if ( db_dirbuild( dbip ) ) { bu_exit(1, "db_dirbuild failed\n"); } BN_CK_TOL(tree_state.ts_tol); RT_CK_TESS_TOL(tree_state.ts_ttol); /* Write out header */ if (inches) fprintf(fp, "# BRL-CAD generated Wavefront OBJ file (Units in)\n"); else fprintf(fp, "# BRL-CAD generated Wavefront OBJ file (Units mm)\n"); fprintf( fp, "# BRL-CAD model: %s\n# BRL_CAD objects:", argv[0] ); for ( c=1; c<argc; c++ ) fprintf( fp, " %s", argv[c] ); fprintf( fp, "\n" ); /* Walk indicated tree(s). Each region will be output separately */ (void) db_walk_tree(dbip, argc-1, (const char **)(argv+1), 1, /* ncpu */ &tree_state, 0, /* take all regions */ do_region_end, nmg_booltree_leaf_tess, (genptr_t)NULL); /* in librt/nmg_bool.c */ percent = 0; if (regions_tried>0) { percent = ((double)regions_converted * 100) / regions_tried; printf("Tried %d regions, %d converted to NMG's successfully. %g%%\n", regions_tried, regions_converted, percent); } percent = 0; if ( regions_tried > 0 ) { percent = ((double)regions_written * 100) / regions_tried; printf( " %d triangulated successfully. %g%%\n", regions_written, percent ); } fclose(fp); /* Release dynamic storage */ nmg_km(the_model); rt_vlist_cleanup(); db_close(dbip); #if MEMORY_LEAK_CHECKING bu_prmem("After complete G-ACAD conversion"); #endif return 0; }
/* * 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); }
int main(int argc, char **argv) { int i, j; int c; double percent; bu_setprogname(argv[0]); bu_setlinebuf(stderr); RTG.debug = 0; ttol.magic = RT_TESS_TOL_MAGIC; /* Defaults, updated by command line options. */ ttol.abs = 0.0; ttol.rel = 0.01; ttol.norm = 0.0; /* FIXME: These need to be improved */ tol.magic = BN_TOL_MAGIC; tol.dist = 0.0005; tol.dist_sq = tol.dist * tol.dist; tol.perp = 1e-6; tol.para = 1 - tol.perp; the_model = (struct model *)NULL; tree_state = rt_initial_tree_state; /* struct copy */ tree_state.ts_m = &the_model; tree_state.ts_tol = &tol; tree_state.ts_ttol = &ttol; rt_init_resource(&rt_uniresource, 0, NULL); /* For visualization purposes, in the debug plot files */ { /* WTF: This value is specific to the Bradley */ nmg_eue_dist = 2.0; } BU_LIST_INIT(&RTG.rtg_vlfree); /* for vlist macros */ /* Get command line arguments. */ while ((c = bu_getopt(argc, argv, "a:n:o:r:vx:P:X:h?")) != -1) { switch (c) { case 'a': /* Absolute tolerance. */ ttol.abs = atof(bu_optarg); ttol.rel = 0.0; break; case 'n': /* Surface normal tolerance. */ ttol.norm = atof(bu_optarg); ttol.rel = 0.0; break; case 'o': /* Output file name */ out_file = bu_optarg; break; case 'r': /* Relative tolerance. */ ttol.rel = atof(bu_optarg); break; case 'v': verbose++; break; case 'P': ncpu = atoi(bu_optarg); break; case 'x': sscanf(bu_optarg, "%x", (unsigned int *)&RTG.debug); break; case 'X': sscanf(bu_optarg, "%x", (unsigned int *)&RTG.NMG_debug); NMG_debug = RTG.NMG_debug; break; default: usage(argv[0]); } } if (bu_optind+1 >= argc) usage(argv[0]); /* Open BRL-CAD database */ if ((dbip = db_open(argv[bu_optind], DB_OPEN_READONLY)) == DBI_NULL) { perror(argv[0]); bu_exit(1, "Cannot open geometry database file %s\n", argv[bu_optind]); } if (db_dirbuild(dbip)) { bu_exit(1, "db_dirbuild failed\n"); } if (out_file == NULL) { fp_out = stdout; setmode(fileno(fp_out), O_BINARY); } else { if ((fp_out = fopen(out_file, "wb")) == NULL) { bu_log("Cannot open %s\n", out_file); perror(argv[0]); return 2; } } bu_optind++; fprintf(fp_out, "$03"); /* First produce an unordered list of region ident codes */ (void)db_walk_tree(dbip, argc-bu_optind, (const char **)(&argv[bu_optind]), 1, /* ncpu */ &tree_state, get_reg_id, /* put id in table */ region_stub, leaf_stub, (void *)NULL); /* Process regions in ident order */ curr_id = 0; for (i = 0; i < ident_length; i++) { int next_id = 99999999; for (j = 0; j < ident_length; j++) { int test_id; test_id = idents[j]; if (test_id > curr_id && test_id < next_id) next_id = test_id; } curr_id = next_id; face_count = 0; bu_log("Processing id %d\n", curr_id); /* Walk indicated tree(s). Each region will be output separately */ tree_state = rt_initial_tree_state; /* struct copy */ the_model = nmg_mm(); tree_state.ts_m = &the_model; tree_state.ts_tol = &tol; tree_state.ts_ttol = &ttol; (void)db_walk_tree(dbip, argc-bu_optind, (const char **)(&argv[bu_optind]), ncpu, &tree_state, select_region, do_region_end, nmg_booltree_leaf_tess, (void *)NULL); /* in librt/nmg_bool.c */ nmg_km(the_model); } percent = 0; if (regions_tried > 0) percent = ((double)regions_converted * 100) / regions_tried; printf("Tried %d regions, %d converted successfully. %g%%\n", regions_tried, regions_converted, percent); percent = 0; if (regions_tried > 0) percent = ((double)regions_written * 100) / regions_tried; printf(" %d written successfully. %g%%\n", regions_written, percent); /* Release dynamic storage */ rt_vlist_cleanup(); db_close(dbip); return 0; }
int main(int argc, char **argv) { int i; int c; struct plate_mode pm; bu_setprogname(argv[0]); bu_setlinebuf( stderr ); the_model = nmg_mm(); tree_state = rt_initial_tree_state; /* struct copy */ tree_state.ts_tol = &tol; tree_state.ts_ttol = &ttol; tree_state.ts_m = &the_model; ttol.magic = RT_TESS_TOL_MAGIC; /* Defaults, updated by command line options. */ ttol.abs = 0.0; ttol.rel = 0.01; ttol.norm = 0.0; /* FIXME: These need to be improved */ tol.magic = BN_TOL_MAGIC; tol.dist = BN_TOL_DIST; tol.dist_sq = tol.dist * tol.dist; tol.perp = 1e-6; tol.para = 1 - tol.perp; /* NOTE: For visualization purposes, in the debug plot files */ { /* WTF: This value is specific to the Bradley */ nmg_eue_dist = 2.0; } BU_LIST_INIT( &RTG.rtg_vlfree ); /* for vlist macros */ BARRIER_CHECK; /* Get command line arguments. */ while ((c = bu_getopt(argc, argv, "d:a:n:o:r:vx:P:X:u:h?")) != -1) { switch (c) { case 'a': /* Absolute tolerance. */ ttol.abs = atof(bu_optarg); ttol.rel = 0.0; break; case 'd': /* calculational tolerance */ tol.dist = atof( bu_optarg ); tol.dist_sq = tol.dist * tol.dist; break; case 'n': /* Surface normal tolerance. */ ttol.norm = atof(bu_optarg)*DEG2RAD; ttol.rel = 0.0; break; case 'o': /* Output file name */ out_file = bu_optarg; break; case 'r': /* Relative tolerance. */ ttol.rel = atof(bu_optarg); break; case 'v': verbose++; break; case 'P': ncpu = atoi(bu_optarg); break; case 'x': sscanf( bu_optarg, "%x", (unsigned int *)&RTG.debug ); break; case 'X': sscanf( bu_optarg, "%x", (unsigned int *)&RTG.NMG_debug ); NMG_debug = RTG.NMG_debug; break; case 'u': units = bu_strdup( bu_optarg ); scale_factor = bu_units_conversion( units ); if ( ZERO(scale_factor) ) bu_exit(1, "Unrecognized units (%s)\n", units ); scale_factor = 1.0 / scale_factor; break; default: print_usage(argv[0]); } } if (bu_optind+1 >= argc) print_usage(argv[0]); /* Open BRL-CAD database */ if ((dbip = db_open( argv[bu_optind], DB_OPEN_READONLY)) == DBI_NULL) { perror(argv[0]); bu_exit(1, "Cannot open geometry database file %s\n", argv[bu_optind] ); } if ( db_dirbuild( dbip ) ) bu_exit(1, "db_dirbuild() failed!\n" ); if (out_file == NULL) { outfp = stdout; setmode(fileno(outfp), O_BINARY); } else { if ((outfp = fopen( out_file, "wb")) == NULL) { perror( argv[0] ); bu_exit(2, "Cannot open %s\n", out_file ); } } writeX3dHeader(outfp, out_file); bu_optind++; BARRIER_CHECK; pm.num_bots = 0; pm.num_nonbots = 0; pm.array_size = 5; pm.bots = (struct rt_bot_internal **)bu_calloc( pm.array_size, sizeof( struct rt_bot_internal *), "pm.bots" ); for ( i=bu_optind; i<argc; i++ ) { struct directory *dp; dp = db_lookup( dbip, argv[i], LOOKUP_QUIET ); if ( dp == RT_DIR_NULL ) { bu_log( "Cannot find %s\n", argv[i] ); continue; } /* light source must be a combination */ if ( !(dp->d_flags & RT_DIR_COMB) ) continue; /* walk trees selecting only light source regions */ (void)db_walk_tree(dbip, 1, (const char **)(&argv[i]), ncpu, &tree_state, select_lights, do_region_end, leaf_tess, (void *)&pm); /* in librt/nmg_bool.c */ } BARRIER_CHECK; /* Walk indicated tree(s). Each non-light-source region will be output separately */ (void)db_walk_tree(dbip, argc-bu_optind, (const char **)(&argv[bu_optind]), ncpu, &tree_state, select_non_lights, do_region_end, leaf_tess, (void *)&pm); /* in librt/nmg_bool.c */ BARRIER_CHECK; /* Release dynamic storage */ nmg_km(the_model); db_close(dbip); /* Now we need to close each group set */ writeX3dEnd(outfp); if ( verbose ) bu_log( "Total of %d regions converted of %d regions attempted\n", regions_converted, regions_tried ); return 0; }
int main(int argc, char *argv[]) { int verbose = 0; int ncpu = 1; /* Number of processors */ char *output_file = NULL; /* output filename */ struct db_i *dbip; struct model *the_model; struct rt_tess_tol ttol; /* tessellation tolerance in mm */ struct db_tree_state tree_state; /* includes tol & model */ int i, use_mc = 0, use_bottess = 0; struct egg_conv_data conv_data; struct gcv_region_end_data gcvwriter = {nmg_to_egg, NULL}; gcvwriter.client_data = (void *)&conv_data; bu_setprogname(argv[0]); bu_setlinebuf(stderr); tree_state = rt_initial_tree_state; /* struct copy */ tree_state.ts_tol = &conv_data.tol; tree_state.ts_ttol = &ttol; tree_state.ts_m = &the_model; /* Set up tessellation tolerance defaults */ ttol.magic = RT_TESS_TOL_MAGIC; /* Defaults, updated by command line options. */ ttol.abs = 0.0; ttol.rel = 0.01; ttol.norm = 0.0; /* Set up calculation tolerance defaults */ /* FIXME: These need to be improved */ conv_data.tol.magic = BN_TOL_MAGIC; conv_data.tol.dist = BN_TOL_DIST; conv_data.tol.dist_sq = conv_data.tol.dist * conv_data.tol.dist; conv_data.tol.perp = 1e-6; conv_data.tol.para = 1 - conv_data.tol.perp; conv_data.tot_polygons = 0; /* make empty NMG model */ the_model = nmg_mm(); BU_LIST_INIT(&RTG.rtg_vlfree); /* for vlist macros */ /* Get command line arguments. */ while ((i = bu_getopt(argc, argv, "a:89n:o:r:vx:D:P:X:h?")) != -1) { switch (i) { case 'a': /* Absolute tolerance. */ ttol.abs = atof(bu_optarg); ttol.rel = 0.0; break; case 'n': /* Surface normal tolerance. */ ttol.norm = atof(bu_optarg); ttol.rel = 0.0; break; case 'o': /* Output file name. */ output_file = bu_optarg; break; case 'r': /* Relative tolerance. */ ttol.rel = atof(bu_optarg); break; case 'v': verbose++; break; case 'P': ncpu = atoi(bu_optarg); break; case 'x': sscanf(bu_optarg, "%x", (unsigned int *)&RTG.debug); break; case 'D': conv_data.tol.dist = atof(bu_optarg); conv_data.tol.dist_sq = conv_data.tol.dist * conv_data.tol.dist; rt_pr_tol(&conv_data.tol); break; case 'X': sscanf(bu_optarg, "%x", (unsigned int *)&RTG.NMG_debug); break; case '8': use_mc = 1; break; case '9': use_bottess = 1; break; default: usage(argv[0]); } } if (bu_optind+1 >= argc) usage(argv[0]); conv_data.fp = stdout; if (output_file) { if ((conv_data.fp=fopen(output_file, "wb+")) == NULL) { perror(argv[0]); bu_exit(1, "Cannot open ASCII output file (%s) for writing\n", output_file); } } /* Open brl-cad database */ argc -= bu_optind; argv += bu_optind; if (argc < 2 || argv[0] == NULL || argv[1] == NULL) usage(argv[0]); gcvwriter.write_region = nmg_to_egg; if ((dbip = db_open(argv[0], DB_OPEN_READONLY)) == DBI_NULL) { perror(argv[0]); bu_exit(1, "Unable to open geometry database file (%s)\n", argv[0]); } if (db_dirbuild(dbip)) { bu_exit(1, "ERROR: db_dirbuild failed\n"); } BN_CK_TOL(tree_state.ts_tol); RT_CK_TESS_TOL(tree_state.ts_ttol); if (verbose) { bu_log("Model: %s\n", argv[0]); bu_log("Objects:"); for (i=1; i<argc; i++) bu_log(" %s", argv[i]); bu_log("\nTessellation tolerances:\n\tabs = %g mm\n\trel = %g\n\tnorm = %g\n", tree_state.ts_ttol->abs, tree_state.ts_ttol->rel, tree_state.ts_ttol->norm); bu_log("Calculational tolerances:\n\tdist = %g mm perp = %g\n", tree_state.ts_tol->dist, tree_state.ts_tol->perp); } /* print the egg header stuff, including the command line to execute it */ fprintf(conv_data.fp, "<CoordinateSystem> { Z-Up }\n\n"); fprintf(conv_data.fp, "<Comment> {\n \"%s", *argv); for (i=1; i<argc; i++) fprintf(conv_data.fp, " %s", argv[i]); fprintf(conv_data.fp, "\"\n}\n"); /* Walk indicated tree(s). Each region will be output separately */ while (--argc) { fprintf(conv_data.fp, "<Group> %s {\n", *(argv+1)); (void) db_walk_tree(dbip, /* db_i */ 1, /* argc */ (const char **)(++argv), /* argv */ ncpu, /* ncpu */ &tree_state, /* state */ NULL, /* start func */ use_mc?gcv_region_end_mc:use_bottess?gcv_bottess_region_end:gcv_region_end, /* end func */ use_mc?NULL:nmg_booltree_leaf_tess, /* leaf func */ (void *)&gcvwriter); /* client_data */ fprintf(conv_data.fp, "}\n"); } bu_log("%ld triangles written\n", conv_data.tot_polygons); if (output_file) fclose(conv_data.fp); /* Release dynamic storage */ nmg_km(the_model); rt_vlist_cleanup(); db_close(dbip); return 0; }
/* * 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; }
int main(int argc, char **argv) { int c; double percent; int i; bu_setprogname(argv[0]); bu_setlinebuf(stderr); RTG.debug = 0; tree_state = rt_initial_tree_state; /* struct copy */ tree_state.ts_tol = &tol; tree_state.ts_ttol = &ttol; tree_state.ts_m = &the_model; ttol.magic = RT_TESS_TOL_MAGIC; /* Defaults, updated by command line options. */ ttol.abs = 0.0; ttol.rel = 0.01; ttol.norm = 0.0; /* FIXME: These need to be improved */ tol.magic = BN_TOL_MAGIC; tol.dist = BN_TOL_DIST; tol.dist_sq = tol.dist * tol.dist; tol.perp = 1e-6; tol.para = 1 - tol.perp; the_model = nmg_mm(); BU_LIST_INIT(&RTG.rtg_vlfree); /* for vlist macros */ /* Get command line arguments. */ while ((c = bu_getopt(argc, argv, "a:n:o:r:vx:D:P:X:e:ih?")) != -1) { switch (c) { case 'a': /* Absolute tolerance. */ ttol.abs = atof(bu_optarg); ttol.rel = 0.0; break; case 'n': /* Surface normal tolerance. */ ttol.norm = atof(bu_optarg); ttol.rel = 0.0; break; case 'o': /* Output file name. */ output_file = bu_optarg; break; case 'r': /* Relative tolerance. */ ttol.rel = atof(bu_optarg); break; case 'v': verbose++; break; case 'P': ncpu = atoi(bu_optarg); break; case 'x': sscanf(bu_optarg, "%x", (unsigned int *)&RTG.debug); break; case 'D': tol.dist = atof(bu_optarg); tol.dist_sq = tol.dist * tol.dist; rt_pr_tol(&tol); break; case 'X': sscanf(bu_optarg, "%x", (unsigned int *)&RTG.NMG_debug); NMG_debug = RTG.NMG_debug; break; case 'e': /* Error file name. */ error_file = bu_optarg; break; case 'i': inches = 1; break; default: usage(argv[0]); } } if (bu_optind+1 >= argc) usage(argv[0]); if (!output_file) { fp = stdout; setmode(fileno(fp), O_BINARY); } else { /* Open output file */ if ((fp=fopen(output_file, "wb+")) == NULL) { perror(argv[0]); bu_exit(1, "Cannot open output file (%s) for writing\n", output_file); } } /* Open g-acad error log file */ if (!error_file) { fpe = stderr; setmode(fileno(fpe), O_BINARY); } else if ((fpe=fopen(error_file, "wb")) == NULL) { perror(argv[0]); bu_exit(1, "Cannot open output file (%s) for writing\n", error_file); } /* Open BRL-CAD database */ argc -= bu_optind; argv += bu_optind; if ((dbip = db_open(argv[0], DB_OPEN_READONLY)) == DBI_NULL) { perror(argv[0]); bu_exit(1, "Cannot open geometry database file (%s)\n", argv[0]); } if (db_dirbuild(dbip)) { bu_exit(1, "db_dirbuild failed\n"); } BN_CK_TOL(tree_state.ts_tol); RT_CK_TESS_TOL(tree_state.ts_ttol); fprintf(fpe, "Model: %s\n", argv[0]); fprintf(fpe, "Objects:"); for (i=1; i<argc; i++) fprintf(fpe, " %s", argv[i]); fprintf(fpe, "\nTessellation tolerances:\n\tabs = %g mm\n\trel = %g\n\tnorm = %g\n", tree_state.ts_ttol->abs, tree_state.ts_ttol->rel, tree_state.ts_ttol->norm); fprintf(fpe, "Calculational tolerances:\n\tdist = %g mm perp = %g\n", tree_state.ts_tol->dist, tree_state.ts_tol->perp); bu_log("Model: %s\n", argv[0]); bu_log("Objects:"); for (i=1; i<argc; i++) bu_log(" %s", argv[i]); bu_log("\nTessellation tolerances:\n\tabs = %g mm\n\trel = %g\n\tnorm = %g\n", tree_state.ts_ttol->abs, tree_state.ts_ttol->rel, tree_state.ts_ttol->norm); bu_log("Calculational tolerances:\n\tdist = %g mm perp = %g\n", tree_state.ts_tol->dist, tree_state.ts_tol->perp); /* Write out ACAD facet header */ if (inches) fprintf(fp, "BRL-CAD generated ACAD FACET FILE (Units in)\n"); else fprintf(fp, "BRL-CAD generated ACAD FACET FILE (Units mm)\n"); /* Generate space for number of facet entities, will write over later */ fprintf(fp, " "); /* Walk indicated tree(s). Each region will be output separately */ (void) db_walk_tree(dbip, argc-1, (const char **)(argv+1), 1, /* ncpu */ &tree_state, 0, /* take all regions */ do_region_end, nmg_booltree_leaf_tess, (void *)NULL); /* in librt/nmg_bool.c */ percent = 0; if (regions_tried>0) { percent = ((double)regions_converted * 100) / regions_tried; printf("Tried %d regions, %d converted to NMG's successfully. %g%%\n", regions_tried, regions_converted, percent); } percent = 0; if (regions_tried > 0) { percent = ((double)regions_written * 100) / regions_tried; printf(" %d triangulated successfully. %g%%\n", regions_written, percent); } bu_log("%ld triangles written\n", tot_polygons); fprintf(fpe, "%ld triangles written\n", tot_polygons); /* Write out number of facet entities to .facet file */ rewind(fp); bu_fseek(fp, 46, 0); /* Re-position pointer to 2nd line */ fprintf(fp, "%d\n", regions_written); /* Write out number of regions */ fclose(fp); /* Release dynamic storage */ nmg_km(the_model); rt_vlist_cleanup(); db_close(dbip); return 0; }
/** * This is the gist for what is going on (not verified): * * 1. initialize tree_state (db_tree_state) * 2. Deal with command line arguments. Strip off everything but regions for processing. * 3. Open geometry (.g) file and build directory db_dirbuild * 4. db_walk_tree (get_layer) for layer names only * 5. Initialize tree_state * 6. Initialize model (nmg)\ * 7. db_walk_tree (gcv_region_end) * 8. Cleanup */ int main(int argc, char *argv[]) { int c; double percent; bu_setlinebuf(stderr); tree_state = rt_initial_tree_state; /* struct copy */ tree_state.ts_tol = &tol; tree_state.ts_ttol = &ttol; tree_state.ts_m = &the_model; /* Set up tessellation tolerance defaults */ ttol.magic = RT_TESS_TOL_MAGIC; /* Defaults, updated by command line options. */ ttol.abs = 0.0; ttol.rel = 0.01; ttol.norm = 0.0; /* Set up calculation tolerance defaults */ /* FIXME: These need to be improved */ tol.magic = BN_TOL_MAGIC; tol.dist = 0.0005; tol.dist_sq = tol.dist * tol.dist; tol.perp = 1e-6; tol.para = 1 - tol.perp; /* init resources we might need */ rt_init_resource(&rt_uniresource, 0, NULL); BU_LIST_INIT(&RTG.rtg_vlfree); /* for vlist macros */ /* Get command line arguments. */ while ((c = bu_getopt(argc, argv, "a:n:o:pr:vx:D:P:X:ih?")) != -1) { switch (c) { case 'a': /* Absolute tolerance. */ ttol.abs = atof(bu_optarg); ttol.rel = 0.0; break; case 'n': /* Surface normal tolerance. */ ttol.norm = atof(bu_optarg); ttol.rel = 0.0; break; case 'o': /* Output file name. */ output_file = bu_optarg; break; case 'p': polyface_mesh = 1; break; case 'r': /* Relative tolerance. */ ttol.rel = atof(bu_optarg); break; case 'v': verbose++; break; case 'P': ncpu = atoi(bu_optarg); break; case 'x': sscanf(bu_optarg, "%x", (unsigned int *)&RTG.debug); break; case 'D': tol.dist = atof(bu_optarg); tol.dist_sq = tol.dist * tol.dist; rt_pr_tol(&tol); break; case 'X': sscanf(bu_optarg, "%x", (unsigned int *)&RTG.NMG_debug); NMG_debug = RTG.NMG_debug; break; case 'i': inches = 1; break; default: usage(argv[0]); bu_exit(1, "%s\n", brlcad_ident("BRL-CAD to DXF Exporter")); break; } } if (bu_optind+1 >= argc) { usage(argv[0]); bu_exit(1, "%s\n", brlcad_ident("BRL-CAD to DXF Exporter")); } if (!output_file) { fp = stdout; setmode(fileno(fp), O_BINARY); } else { /* Open output file */ if ((fp=fopen(output_file, "w+b")) == NULL) { perror(argv[0]); bu_exit(1, " Cannot open output file (%s) for writing\n", output_file); } } /* Open BRL-CAD database */ argc -= bu_optind; argv += bu_optind; if ((dbip = db_open(argv[0], DB_OPEN_READONLY)) == DBI_NULL) { perror(argv[0]); bu_exit(1, "Unable to open geometry database file (%s)\n", argv[0]); } if (db_dirbuild(dbip)) { bu_exit(1, "db_dirbuild failed\n"); } BN_CK_TOL(tree_state.ts_tol); RT_CK_TESS_TOL(tree_state.ts_ttol); if (verbose) { int i; bu_log("Model: %s\n", argv[0]); bu_log("Objects:"); for (i = 1; i < argc; i++) bu_log(" %s", argv[i]); bu_log("\nTessellation tolerances:\n\tabs = %g mm\n\trel = %g\n\tnorm = %g\n", tree_state.ts_ttol->abs, tree_state.ts_ttol->rel, tree_state.ts_ttol->norm); bu_log("Calculational tolerances:\n\tdist = %g mm perp = %g\n", tree_state.ts_tol->dist, tree_state.ts_tol->perp); } /* output DXF header and start of TABLES section */ fprintf(fp, "0\nSECTION\n2\nHEADER\n999\n%s\n0\nENDSEC\n0\nSECTION\n2\nTABLES\n0\nTABLE\n2\nLAYER\n", argv[argc-1]); /* Walk indicated tree(s) just for layer names to put in TABLES section */ (void)db_walk_tree(dbip, argc-1, (const char **)(argv+1), 1, /* ncpu */ &tree_state, 0, /* take all regions */ get_layer, NULL, (void *)NULL); /* in librt/nmg_bool.c */ /* end of layers section, start of ENTITIES SECTION */ fprintf(fp, "0\nENDTAB\n0\nENDSEC\n0\nSECTION\n2\nENTITIES\n"); /* Walk indicated tree(s). Each region will be output separately */ tree_state = rt_initial_tree_state; /* struct copy */ tree_state.ts_tol = &tol; tree_state.ts_ttol = &ttol; /* make empty NMG model */ the_model = nmg_mm(); tree_state.ts_m = &the_model; (void) db_walk_tree(dbip, argc-1, (const char **)(argv+1), 1, /* ncpu */ &tree_state, 0, /* take all regions */ gcv_region_end, nmg_booltree_leaf_tess, (void *)&gcvwriter); /* callback for gcv_region_end */ percent = 0; if (regions_tried>0) { percent = ((double)regions_converted * 100) / regions_tried; if (verbose) bu_log("Tried %d regions, %d converted to NMG's successfully. %g%%\n", regions_tried, regions_converted, percent); } percent = 0; if (regions_tried > 0) { percent = ((double)regions_written * 100) / regions_tried; if (verbose) bu_log(" %d triangulated successfully. %g%%\n", regions_written, percent); } bu_log("%ld triangles written\n", (long int)tot_polygons); fprintf(fp, "0\nENDSEC\n0\nEOF\n"); if (output_file) { fclose(fp); } /* Release dynamic storage */ nmg_km(the_model); rt_vlist_cleanup(); db_close(dbip); return 0; }
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); }
int ged_shells(struct ged *gedp, int argc, const char *argv[]) { struct directory *old_dp, *new_dp; struct rt_db_internal old_intern, new_intern; struct model *m_tmp, *m; struct nmgregion *r_tmp, *r; struct shell *s_tmp, *s; int shell_count=0; struct bu_vls shell_name = BU_VLS_INIT_ZERO; long **trans_tbl; static const char *usage = "nmg_model"; 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 != 2) { bu_vls_printf(gedp->ged_result_str, "Usage: %s %s", argv[0], usage); return GED_ERROR; } if ((old_dp = db_lookup(gedp->ged_wdbp->dbip, argv[1], LOOKUP_NOISY)) == RT_DIR_NULL) return GED_ERROR; if (rt_db_get_internal(&old_intern, old_dp, gedp->ged_wdbp->dbip, bn_mat_identity, &rt_uniresource) < 0) { bu_vls_printf(gedp->ged_result_str, "rt_db_get_internal() error\n"); return GED_ERROR; } if (old_intern.idb_type != ID_NMG) { bu_vls_printf(gedp->ged_result_str, "Object is not an NMG!!!\n"); return GED_ERROR; } m = (struct model *)old_intern.idb_ptr; NMG_CK_MODEL(m); for (BU_LIST_FOR(r, nmgregion, &m->r_hd)) { for (BU_LIST_FOR(s, shell, &r->s_hd)) { s_tmp = nmg_dup_shell(s, &trans_tbl, &gedp->ged_wdbp->wdb_tol); bu_free((void *)trans_tbl, "trans_tbl"); m_tmp = nmg_mmr(); r_tmp = BU_LIST_FIRST(nmgregion, &m_tmp->r_hd); BU_LIST_DEQUEUE(&s_tmp->l); BU_LIST_APPEND(&r_tmp->s_hd, &s_tmp->l); s_tmp->r_p = r_tmp; nmg_m_reindex(m_tmp, 0); nmg_m_reindex(m, 0); bu_vls_printf(&shell_name, "shell.%d", shell_count); while (db_lookup(gedp->ged_wdbp->dbip, bu_vls_addr(&shell_name), 0) != RT_DIR_NULL) { bu_vls_trunc(&shell_name, 0); shell_count++; bu_vls_printf(&shell_name, "shell.%d", shell_count); } /* Export NMG as a new solid */ RT_DB_INTERNAL_INIT(&new_intern); new_intern.idb_major_type = DB5_MAJORTYPE_BRLCAD; new_intern.idb_type = ID_NMG; new_intern.idb_meth = &OBJ[ID_NMG]; new_intern.idb_ptr = (void *)m_tmp; new_dp=db_diradd(gedp->ged_wdbp->dbip, bu_vls_addr(&shell_name), RT_DIR_PHONY_ADDR, 0, RT_DIR_SOLID, (void *)&new_intern.idb_type); if (new_dp == RT_DIR_NULL) { bu_vls_printf(gedp->ged_result_str, "An error has occurred while adding a new object to the database.\n"); return GED_ERROR; } /* make sure the geometry/bounding boxes are up to date */ nmg_rebound(m_tmp, &gedp->ged_wdbp->wdb_tol); if (rt_db_put_internal(new_dp, gedp->ged_wdbp->dbip, &new_intern, &rt_uniresource) < 0) { /* Free memory */ nmg_km(m_tmp); bu_vls_printf(gedp->ged_result_str, "rt_db_put_internal() failure\n"); return GED_ERROR; } /* Internal representation has been freed by rt_db_put_internal */ new_intern.idb_ptr = (void *)NULL; } } bu_vls_free(&shell_name); return GED_OK; }
int ged_bot_fuse(struct ged *gedp, int argc, const char **argv) { struct directory *old_dp, *new_dp; struct rt_db_internal intern, intern2; struct rt_bot_internal *bot; int count=0; static const char *usage = "new_bot old_bot"; struct model *m; struct nmgregion *r; int ret, c, i; struct bn_tol *tol = &gedp->ged_wdbp->wdb_tol; int total = 0; volatile int out_type = 0; /* open edge output type: 0 = none, 1 = show, 2 = plot */ size_t open_cnt; struct bu_vls name_prefix = BU_VLS_INIT_ZERO; /* bu_getopt() options */ static const char *bot_fuse_options = "sp"; static const char *bot_fuse_options_str = "[-s|-p]"; 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 != 3 && argc != 4) { bu_vls_printf(gedp->ged_result_str, "Usage: %s %s %s", argv[0], bot_fuse_options_str, usage); return GED_HELP; } /* Turn off getopt's error messages */ bu_opterr = 0; bu_optind = 1; /* get all the option flags from the command line */ while ((c=bu_getopt(argc, (char **)argv, bot_fuse_options)) != -1) { switch (c) { case 's': { out_type = 1; /* show open edges */ break; } case 'p': { out_type = 2; /* plot open edges */ break; } default : { bu_vls_printf(gedp->ged_result_str, "Unknown option: '%c'", c); return GED_HELP; } } } i = argc - 2; bu_log("%s: start\n", argv[0]); GED_DB_LOOKUP(gedp, old_dp, argv[i+1], LOOKUP_NOISY, GED_ERROR & GED_QUIET); GED_DB_GET_INTERNAL(gedp, &intern, old_dp, bn_mat_identity, &rt_uniresource, GED_ERROR); if (intern.idb_major_type != DB5_MAJORTYPE_BRLCAD || intern.idb_minor_type != DB5_MINORTYPE_BRLCAD_BOT) { bu_vls_printf(gedp->ged_result_str, "%s: %s is not a BOT solid!\n", argv[0], argv[i+1]); return GED_ERROR; } /* create nmg model structure */ m = nmg_mm(); /* place bot in nmg structure */ bu_log("%s: running rt_bot_tess\n", argv[0]); ret = rt_bot_tess(&r, m, &intern, &gedp->ged_wdbp->wdb_ttol, tol); /* free internal representation of original bot */ rt_db_free_internal(&intern); if (ret != 0) { bu_vls_printf(gedp->ged_result_str, "%s: %s fuse failed (1).\n", argv[0], argv[i+1]); nmg_km(m); return GED_ERROR; } total = 0; /* Step 1 -- the vertices. */ bu_log("%s: running nmg_vertex_fuse\n", argv[0]); count = nmg_vertex_fuse(&m->magic, tol); total += count; bu_log("%s: %s, %d vertex fused\n", argv[0], argv[i+1], count); /* Step 1.5 -- break edges on vertices, before fusing edges */ bu_log("%s: running nmg_break_e_on_v\n", argv[0]); count = nmg_break_e_on_v(&m->magic, tol); total += count; bu_log("%s: %s, %d broke 'e' on 'v'\n", argv[0], argv[i+1], count); if (total) { struct nmgregion *r2; struct shell *s; bu_log("%s: running nmg_make_faces_within_tol\n", argv[0]); /* vertices and/or edges have been moved, * may have created out-of-tolerance faces */ for (BU_LIST_FOR(r2, nmgregion, &m->r_hd)) { for (BU_LIST_FOR(s, shell, &r2->s_hd)) nmg_make_faces_within_tol(s, tol); } } /* Step 2 -- the face geometry */ bu_log("%s: running nmg_model_face_fuse\n", argv[0]); count = nmg_model_face_fuse(m, tol); total += count; bu_log("%s: %s, %d faces fused\n", argv[0], argv[i+1], count); /* Step 3 -- edges */ bu_log("%s: running nmg_edge_fuse\n", argv[0]); count = nmg_edge_fuse(&m->magic, tol); total += count; bu_log("%s: %s, %d edges fused\n", argv[0], argv[i+1], count); bu_log("%s: %s, %d total fused\n", argv[0], argv[i+1], total); if (!BU_SETJUMP) { /* try */ /* convert the nmg model back into a bot */ bot = nmg_bot(BU_LIST_FIRST(shell, &r->s_hd), tol); bu_vls_sprintf(&name_prefix, "open_edges.%s", argv[i]); bu_log("%s: running show_dangling_edges\n", argv[0]); open_cnt = show_dangling_edges(gedp, &m->magic, bu_vls_addr(&name_prefix), out_type); bu_log("%s: WARNING %ld open edges, new BOT may be invalid!!!\n", argv[0], open_cnt); bu_vls_free(&name_prefix); /* free the nmg model structure */ nmg_km(m); } else { /* catch */ BU_UNSETJUMP; bu_vls_printf(gedp->ged_result_str, "%s: %s fuse failed (2).\n", argv[0], argv[i+1]); return GED_ERROR; } BU_UNSETJUMP; RT_DB_INTERNAL_INIT(&intern2); intern2.idb_major_type = DB5_MAJORTYPE_BRLCAD; intern2.idb_type = ID_BOT; intern2.idb_meth = &OBJ[ID_BOT]; intern2.idb_ptr = (void *)bot; GED_DB_DIRADD(gedp, new_dp, argv[i], RT_DIR_PHONY_ADDR, 0, RT_DIR_SOLID, (void *)&intern2.idb_type, GED_ERROR); GED_DB_PUT_INTERNAL(gedp, new_dp, &intern2, &rt_uniresource, GED_ERROR); bu_log("%s: Created new BOT (%s)\n", argv[0], argv[i]); bu_log("%s: Done.\n", argv[0]); return GED_OK; }
/* * This routine is the drawable geometry object's analog of rt_gettrees(). * Add a set of tree hierarchies to the active set. * Note that argv[0] should be ignored, it has the command name in it. * * Returns - * 0 Ordinarily * -1 On major error */ int _ged_drawtrees(struct ged *gedp, int argc, const char *argv[], int kind, struct _ged_client_data *_dgcdp) { int ret = 0; int c; int ncpu = 1; int nmg_use_tnurbs = 0; int enable_fastpath = 0; struct model *nmg_model; struct _ged_client_data dgcdp; int i; int ac = 1; char *av[3]; RT_CHECK_DBI(gedp->ged_wdbp->dbip); if (argc <= 0) return -1; /* FAIL */ ++drawtrees_depth; av[1] = (char *)0; /* options are already parsed into _dgcdp */ if (_dgcdp != (struct _ged_client_data *)0) { dgcdp = *_dgcdp; /* struct copy */ } else { struct bview *gvp; memset(&dgcdp, 0, sizeof(struct _ged_client_data)); dgcdp.gedp = gedp; gvp = gedp->ged_gvp; if (gvp && gvp->gv_adaptive_plot) dgcdp.autoview = 1; else dgcdp.autoview = 0; /* Initial values for options, must be reset each time */ dgcdp.draw_nmg_only = 0; /* no booleans */ dgcdp.nmg_triangulate = 1; dgcdp.draw_wireframes = 0; dgcdp.draw_normals = 0; dgcdp.draw_solid_lines_only = 0; dgcdp.draw_no_surfaces = 0; dgcdp.shade_per_vertex_normals = 0; dgcdp.draw_edge_uses = 0; dgcdp.wireframe_color_override = 0; dgcdp.fastpath_count = 0; dgcdp.shaded_mode_override = _GED_SHADED_MODE_UNSET; /* default color - red */ dgcdp.wireframe_color[0] = 255; dgcdp.wireframe_color[1] = 0; dgcdp.wireframe_color[2] = 0; /* default transparency - opaque */ dgcdp.transparency = 1.0; /* freesolid */ dgcdp.freesolid = gedp->freesolid; enable_fastpath = 0; /* Parse options. */ bu_optind = 0; /* re-init bu_getopt() */ while ((c = bu_getopt(argc, (char * const *)argv, "dfhm:nqstuvwx:C:STP:A:oR")) != -1) { switch (c) { case 'u': dgcdp.draw_edge_uses = 1; break; case 's': dgcdp.draw_solid_lines_only = 1; break; case 't': nmg_use_tnurbs = 1; break; case 'v': dgcdp.shade_per_vertex_normals = 1; break; case 'w': dgcdp.draw_wireframes = 1; break; case 'S': dgcdp.draw_no_surfaces = 1; break; case 'T': dgcdp.nmg_triangulate = 0; break; case 'n': dgcdp.draw_normals = 1; break; case 'P': ncpu = atoi(bu_optarg); break; case 'q': dgcdp.do_not_draw_nmg_solids_during_debugging = 1; break; case 'd': dgcdp.draw_nmg_only = 1; break; case 'f': enable_fastpath = 1; break; case 'C': { int r, g, b; char *cp = bu_optarg; r = atoi(cp); while ((*cp >= '0' && *cp <= '9')) cp++; while (*cp && (*cp < '0' || *cp > '9')) cp++; g = atoi(cp); while ((*cp >= '0' && *cp <= '9')) cp++; while (*cp && (*cp < '0' || *cp > '9')) cp++; b = atoi(cp); if (r < 0 || r > 255) r = 255; if (g < 0 || g > 255) g = 255; if (b < 0 || b > 255) b = 255; dgcdp.wireframe_color_override = 1; dgcdp.wireframe_color[0] = r; dgcdp.wireframe_color[1] = g; dgcdp.wireframe_color[2] = b; } break; case 'h': dgcdp.hiddenLine = 1; dgcdp.shaded_mode_override = _GED_SHADED_MODE_ALL; break; case 'm': dgcdp.shaded_mode_override = atoi(bu_optarg); switch (dgcdp.shaded_mode_override) { case 0: dgcdp.shaded_mode_override = _GED_WIREFRAME; break; case 1: dgcdp.shaded_mode_override = _GED_SHADED_MODE_BOTS; break; case 2: dgcdp.shaded_mode_override = _GED_SHADED_MODE_ALL; break; case 3: dgcdp.shaded_mode_override = _GED_SHADED_MODE_EVAL; break; default: if (dgcdp.shaded_mode_override < 0) { dgcdp.shaded_mode_override = _GED_SHADED_MODE_UNSET; } else { dgcdp.shaded_mode_override = _GED_SHADED_MODE_ALL; } } break; case 'x': dgcdp.transparency = atof(bu_optarg); /* clamp it to [0, 1] */ if (dgcdp.transparency < 0.0) dgcdp.transparency = 0.0; if (1.0 < dgcdp.transparency) dgcdp.transparency = 1.0; break; case 'R': dgcdp.autoview = 0; break; case 'A': case 'o': /* nothing to do, handled by edit_com wrapper on the front-end */ break; default: { bu_vls_printf(gedp->ged_result_str, "unrecognized option - %c\n", c); --drawtrees_depth; return GED_ERROR; } } } argc -= bu_optind; argv += bu_optind; switch (kind) { case _GED_DRAW_WIREFRAME: dgcdp.dmode = _GED_WIREFRAME; if (dgcdp.shaded_mode_override != _GED_SHADED_MODE_UNSET) { dgcdp.dmode = dgcdp.shaded_mode_override; } else if (gedp->ged_gdp->gd_shaded_mode) { dgcdp.dmode = gedp->ged_gdp->gd_shaded_mode; } break; case _GED_DRAW_NMG_POLY: dgcdp.dmode = _GED_BOOL_EVAL; break; } } if (!argc) { bu_vls_printf(gedp->ged_result_str, "Please specify one or more objects to be drawn.\n"); --drawtrees_depth; return -1; } switch (kind) { default: bu_vls_printf(gedp->ged_result_str, "ERROR, bad kind\n"); --drawtrees_depth; return -1; case _GED_DRAW_WIREFRAME: /* * If asking for wireframe and in shaded_mode and no shaded mode override, * or asking for wireframe and shaded mode is being overridden with a value * greater than 0, then draw shaded polygons for each object's primitives if possible. * * Note - * If shaded_mode is _GED_SHADED_MODE_BOTS, only BOTS and polysolids * will be shaded. The rest is drawn as wireframe. * If shaded_mode is _GED_SHADED_MODE_ALL, everything except pipe solids * are drawn as shaded polygons. */ if (dgcdp.dmode == _GED_SHADED_MODE_BOTS || dgcdp.dmode == _GED_SHADED_MODE_ALL || dgcdp.dmode == _GED_SHADED_MODE_EVAL) { struct _ged_client_data dgcdp_save; for (i = 0; i < argc; ++i) { if (drawtrees_depth == 1) dgcdp.gdlp = dl_addToDisplay(gedp->ged_gdp->gd_headDisplay, gedp->ged_wdbp->dbip, argv[i]); if (dgcdp.gdlp == GED_DISPLAY_LIST_NULL) continue; dgcdp_save = dgcdp; if (dgcdp.dmode == _GED_SHADED_MODE_EVAL) { ret = plot_shaded_eval(gedp, argv[i], &dgcdp); if (ret == GED_OK) { continue; } /* if evaluated shading failed, fall back to "all" mode */ dgcdp.gedp->ged_gdp->gd_shaded_mode = 0; dgcdp.shaded_mode_override = _GED_SHADED_MODE_ALL; dgcdp.dmode = _GED_SHADED_MODE_ALL; } av[0] = (char *)argv[i]; ret = db_walk_tree(gedp->ged_wdbp->dbip, ac, (const char **)av, ncpu, &gedp->ged_wdbp->wdb_initial_tree_state, NULL, draw_check_region_end, draw_check_leaf, (void *)&dgcdp); dgcdp = dgcdp_save; } } else { struct display_list **paths_to_draw; struct display_list *gdlp; paths_to_draw = (struct display_list **) bu_malloc(sizeof(struct display_list *) * argc, "redraw paths"); /* create solids */ for (i = 0; i < argc; ++i) { struct bview_client_data bview_data; bview_data.draw_solid_lines_only = dgcdp.draw_solid_lines_only; bview_data.wireframe_color_override = dgcdp.wireframe_color_override; bview_data.wireframe_color[0]= dgcdp.wireframe_color[0]; bview_data.wireframe_color[1]= dgcdp.wireframe_color[1]; bview_data.wireframe_color[2]= dgcdp.wireframe_color[2]; bview_data.transparency= dgcdp.transparency; bview_data.dmode = dgcdp.dmode; bview_data.hiddenLine = dgcdp.hiddenLine; bview_data.freesolid = (void *)gedp->freesolid; dgcdp.gdlp = dl_addToDisplay(gedp->ged_gdp->gd_headDisplay, gedp->ged_wdbp->dbip, argv[i]); bview_data.gdlp = dgcdp.gdlp; /* store draw path */ paths_to_draw[i] = dgcdp.gdlp; if (dgcdp.gdlp == GED_DISPLAY_LIST_NULL) { continue; } av[0] = (char *)argv[i]; ret = db_walk_tree(gedp->ged_wdbp->dbip, ac, (const char **)av, ncpu, &gedp->ged_wdbp->wdb_initial_tree_state, NULL, wireframe_region_end, append_solid_to_display_list, (void *)&bview_data); } /* We need to know the view size in order to choose * appropriate input values for the adaptive plot * routines. Unless we're keeping the current view, * we need to autoview now so we have the correct * view size for plotting. */ if (dgcdp.autoview) { const char *autoview_args[2] = {"autoview", NULL}; ged_autoview(gedp, 1, autoview_args); } /* calculate plot vlists for solids of each draw path */ for (i = 0; i < argc; ++i) { gdlp = paths_to_draw[i]; if (gdlp == GED_DISPLAY_LIST_NULL) { continue; } ret = dl_redraw(gdlp, gedp->ged_wdbp->dbip, &gedp->ged_wdbp->wdb_initial_tree_state, gedp->ged_gvp, gedp->ged_create_vlist_callback); if (ret < 0) { bu_vls_printf(gedp->ged_result_str, "%s: %s redraw failure\n", argv[0], argv[i]); return GED_ERROR; } } bu_free(paths_to_draw, "draw paths"); } break; case _GED_DRAW_NMG_POLY: { nmg_model = nmg_mm(); gedp->ged_wdbp->wdb_initial_tree_state.ts_m = &nmg_model; if (dgcdp.draw_edge_uses) { bu_vls_printf(gedp->ged_result_str, "Doing the edgeuse thang (-u)\n"); dgcdp.draw_edge_uses_vbp = rt_vlblock_init(); } for (i = 0; i < argc; ++i) { if (drawtrees_depth == 1) dgcdp.gdlp = dl_addToDisplay(gedp->ged_gdp->gd_headDisplay, gedp->ged_wdbp->dbip, argv[i]); if (dgcdp.gdlp == GED_DISPLAY_LIST_NULL) continue; av[0] = (char *)argv[i]; ret = db_walk_tree(gedp->ged_wdbp->dbip, ac, (const char **)av, ncpu, &gedp->ged_wdbp->wdb_initial_tree_state, enable_fastpath ? draw_nmg_region_start : 0, draw_nmg_region_end, nmg_use_tnurbs ? nmg_booltree_leaf_tnurb : nmg_booltree_leaf_tess, (void *)&dgcdp); } if (dgcdp.draw_edge_uses) { _ged_cvt_vlblock_to_solids(gedp, dgcdp.draw_edge_uses_vbp, "_EDGEUSES_", 0); bn_vlblock_free(dgcdp.draw_edge_uses_vbp); dgcdp.draw_edge_uses_vbp = (struct bn_vlblock *)NULL; } /* Destroy NMG */ nmg_km(nmg_model); break; } } --drawtrees_depth; if (dgcdp.fastpath_count) { bu_log("%d region%s rendered through polygon fastpath\n", dgcdp.fastpath_count, dgcdp.fastpath_count == 1 ? "" : "s"); } if (ret < 0) return -1; return 0; /* OK */ }
int brep(int entityno) { int sol_num; /* IGES solid type number */ int shell_de; /* Directory sequence number for a shell */ int orient; /* Orientation of shell */ int *void_shell_de; /* Directory sequence number for an void shell */ int *void_orient; /* Orientation of void shell */ int num_of_voids; /* Number of inner void shells */ struct model *m; /* NMG model */ struct nmgregion *r; /* NMG region */ struct shell **void_shells; /* List of void shells */ struct shell *s_outer; /* Outer shell */ struct iges_vertex_list *v_list; struct iges_edge_list *e_list; int i; /* 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 , ""); Readint(&shell_de , ""); Readint(&orient , ""); Readint(&num_of_voids , ""); if (num_of_voids) { void_shell_de = (int *)bu_calloc(num_of_voids , sizeof(int) , "BREP: void shell DE's"); void_orient = (int *)bu_calloc(num_of_voids , sizeof(int) , "BREP: void shell orients"); void_shells = (struct shell **)bu_calloc(num_of_voids , sizeof(struct shell *) , "BREP: void shell pointers"); for (i = 0; i < num_of_voids; i++) { Readint(&void_shell_de[i] , ""); Readint(&void_orient[i] , ""); } } else { void_shell_de = NULL; void_orient = NULL; void_shells = NULL; } /* start building */ m = nmg_mmr(); r = BU_LIST_FIRST(nmgregion, &m->r_hd); /* Put outer shell in region */ if ((s_outer = Get_outer_shell(r , (shell_de - 1)/2)) == (struct shell *)NULL) goto err; ON_Brep* outer = ON_Brep::New(); if (Get_outer_brep(outer, (shell_de - 1)/2, orient)) goto err; /* Put voids in */ for (i = 0; i < num_of_voids; i++) { if ((void_shells[i] = Add_inner_shell(r, (void_shell_de[i] - 1)/2)) == (struct shell *)NULL) goto err; } /* orient loops */ Orient_loops(r); /* orient shells */ nmg_fix_normals(s_outer , &tol); for (i = 0; i < num_of_voids; i++) { nmg_fix_normals(void_shells[i] , &tol); nmg_invert_shell(void_shells[i]); } if (do_bots) { /* Merge all shells into one */ for (i = 0; i < num_of_voids; i++) nmg_js(s_outer, void_shells[i], &tol); /* write out BOT */ if (mk_bot_from_nmg(fdout, dir[entityno]->name, s_outer)) goto err; } else { /* Compute "geometry" for region and shell */ nmg_region_a(r , &tol); /* Write NMG solid */ if (mk_nmg(fdout , dir[entityno]->name , m)) goto err; } if (num_of_voids) { bu_free((char *)void_shell_de , "BREP: void shell DE's"); bu_free((char *)void_orient , "BREP: void shell orients"); bu_free((char *)void_shells , "brep: void shell list"); } v_list = vertex_root; while (v_list != NULL) { bu_free((char *)v_list->i_verts , "brep: iges_vertex"); bu_free((char *)v_list , "brep: vertex list"); v_list = v_list->next; } vertex_root = NULL; e_list = edge_root; while (e_list != NULL) { bu_free((char *)e_list->i_edge , "brep:iges_edge"); bu_free((char *)e_list , "brep: edge list"); e_list = e_list->next; } edge_root = NULL; return 1; err : if (num_of_voids) { bu_free((char *)void_shell_de , "BREP: void shell DE's"); bu_free((char *)void_orient , "BREP: void shell orients"); bu_free((char *)void_shells , "brep: void shell list"); } nmg_km(m); return 0; }
int main(int argc, char **argv) { int c; double percent; bu_setprogname(argv[0]); bu_setlinebuf(stderr); tree_state = rt_initial_tree_state; /* struct copy */ tree_state.ts_tol = &tol; tree_state.ts_ttol = &ttol; tree_state.ts_m = &the_model; /* Set up tessellation tolerance defaults */ ttol.magic = RT_TESS_TOL_MAGIC; /* Defaults, updated by command line options. */ ttol.abs = 0.0; ttol.rel = 0.01; ttol.norm = 0.0; /* Set up calculation tolerance defaults */ /* FIXME: These need to be improved */ tol.magic = BN_TOL_MAGIC; tol.dist = 0.0005; tol.dist_sq = tol.dist * tol.dist; tol.perp = 1e-6; tol.para = 1 - tol.perp; /* init resources we might need */ rt_init_resource(&rt_uniresource, 0, NULL); /* make empty NMG model */ the_model = nmg_mm(); /* Get command line arguments. */ while ((c = bu_getopt(argc, argv, "r:a:n:o:vx:D:X:h?")) != -1) { switch (c) { case 'r': /* Relative tolerance. */ ttol.rel = atof(bu_optarg); break; case 'a': /* Absolute tolerance. */ ttol.abs = atof(bu_optarg); ttol.rel = 0.0; break; case 'n': /* Surface normal tolerance. */ ttol.norm = atof(bu_optarg); ttol.rel = 0.0; break; case 'o': /* Output file name. */ /* grab output file name */ break; case 'v': verbose++; break; case 'x': sscanf(bu_optarg, "%x", (unsigned int *)&RTG.debug); break; case 'D': tol.dist = atof(bu_optarg); tol.dist_sq = tol.dist * tol.dist; rt_pr_tol(&tol); break; case 'X': sscanf(bu_optarg, "%x", (unsigned int *)&RTG.NMG_debug); NMG_debug = RTG.NMG_debug; break; default: bu_exit(1, usage, argv[0]); } } if (bu_optind+1 >= argc) bu_exit(1, usage, argv[0]); /* Open output file */ /* Open BRL-CAD database */ argc -= bu_optind; argv += bu_optind; if ((dbip = db_open(argv[0], DB_OPEN_READONLY)) == DBI_NULL) { perror(argv[0]); bu_exit(1, "ERROR: Unable to open geometry database file (%s)\n", argv[0]); } if (db_dirbuild(dbip)) bu_exit(1, "db_dirbuild failed\n"); BN_CK_TOL(tree_state.ts_tol); RT_CK_TESS_TOL(tree_state.ts_ttol); if (verbose) { int i; bu_log("Model: %s\n", argv[0]); bu_log("Objects:"); for (i = 1; i < argc; i++) bu_log(" %s", argv[i]); bu_log("\nTessellation tolerances:\n\tabs = %g mm\n\trel = %g\n\tnorm = %g\n", tree_state.ts_ttol->abs, tree_state.ts_ttol->rel, tree_state.ts_ttol->norm); bu_log("Calculational tolerances:\n\tdist = %g mm perp = %g\n", tree_state.ts_tol->dist, tree_state.ts_tol->perp); } /* Walk indicated tree(s). Each region will be output separately */ (void) db_walk_tree(dbip, argc-1, (const char **)(argv+1), 1, /* ncpu */ &tree_state, 0, /* take all regions */ do_region_end, nmg_booltree_leaf_tess, (void *)NULL); /* in librt/nmg_bool.c */ percent = 0; if (regions_tried>0) { percent = ((double)regions_converted * 100) / regions_tried; bu_log("Tried %d regions, %d converted to NMG's successfully. %g%%\n", regions_tried, regions_converted, percent); } percent = 0; if (regions_tried > 0) { percent = ((double)regions_written * 100) / regions_tried; bu_log(" %d triangulated successfully. %g%%\n", regions_written, percent); } bu_log("%zd triangles written\n", tot_polygons); bu_log("Tessellation parameters used:\n"); bu_log(" abs [-a] %g\n", ttol.abs); bu_log(" rel [-r] %g\n", ttol.rel); bu_log(" norm [-n] %g\n", ttol.norm); bu_log(" dist [-D] %g\n", tol.dist); /* Release dynamic storage */ nmg_km(the_model); rt_vlist_cleanup(); db_close(dbip); return 0; }
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; }