extern "C" void
rt_bot_brep(ON_Brep **b, const struct rt_db_internal *ip, const struct bn_tol *tol)
{
    struct rt_db_internal *tmp_internal;
    struct rt_tess_tol ttmptol;

    BU_ALLOC(tmp_internal, struct rt_db_internal);
    RT_DB_INTERNAL_INIT(tmp_internal);

    ttmptol.abs = 0;
    ttmptol.rel = 0.01;
    ttmptol.norm = 0;

    const struct rt_tess_tol *ttol = &ttmptol;
    struct model *botm = nmg_mm();
    struct nmgregion *botr;

    tmp_internal->idb_ptr = (void *)ip->idb_ptr;
    (void)rt_bot_tess(&botr, botm, tmp_internal, ttol, tol);
    tmp_internal->idb_ptr = (void *)botm;
    rt_nmg_brep(b, tmp_internal, tol);

    FREE_MODEL(botm);
    bu_free(tmp_internal, "free temporary rt_db_internal");
}
Esempio n. 2
0
/**
 * R T _ E B M _ B R E P
 */
extern "C" void
rt_ebm_brep(ON_Brep **b, const struct rt_db_internal *ip, const struct bn_tol *tol)
{
    struct rt_db_internal *tmp_internal;
    struct rt_tess_tol ttmptol;

    BU_ALLOC(tmp_internal, struct rt_db_internal);
    RT_DB_INTERNAL_INIT(tmp_internal);

    ttmptol.abs = 0;
    ttmptol.rel = 0.01;
    ttmptol.norm = 0;

    const struct rt_tess_tol *ttol = &ttmptol;
    struct model *ebmm = nmg_mm();
    struct nmgregion *ebmr;

    tmp_internal->idb_ptr = (genptr_t)ip->idb_ptr;
    rt_ebm_tess(&ebmr, ebmm, tmp_internal, ttol, tol);
    tmp_internal->idb_ptr = (genptr_t)ebmm;
    rt_nmg_brep(b, tmp_internal, tol);

    FREE_MODEL(ebmm);
    bu_free(tmp_internal, "free temporary rt_db_internal");
}
/*
 *	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;
    }
}
Esempio n. 5
0
/*
 * Call parse_args to handle command line arguments first, then
 * process input.
 */
int
main(int ac, char *av[])
{
    struct bn_tol tol;
    FILE *fdplot;
    struct rt_wdb *fdmodel;

    parse_args(ac, av);
    if (ac==1) usage((char *)NULL,0);
    if (!manifold[0] && !manifold[1] && !manifold[2] && !manifold[3])
	usage("No manifolds selected\n",1);


    m = nmg_mm();
    r = nmg_mrsv(m);
    s = BU_LIST_FIRST(shell, &r->s_hd);

    tol.magic = BN_TOL_MAGIC;
    tol.dist = 0.01;
    tol.dist_sq = tol.dist * tol.dist;
    tol.perp = 0.001;
    tol.para = 0.999;

    if (manifold[3]) make_3manifold_bits(&tol);
    if (manifold[2]) make_2manifold_bits(&tol);
    if (manifold[1]) make_1manifold_bits();
    if (manifold[0]) make_0manifold_bits();

    NMG_CK_MODEL(m);

    /* write a plot file */
    if ((fdplot = fopen(plotfilename, "w")) == (FILE *)NULL)
	perror(plotfilename);
    else {
	nmg_pl_m(fdplot, m);
	fclose(fdplot);
    }

    /* write the database */
    if ((fdmodel = wdb_fopen(mfilename)) == NULL)
	perror(mfilename);
    else {
	mk_id(fdmodel, "hairy NMG");
	mk_nmg(fdmodel, "s.NMG",  m); /* releases m, boo */

	/* build a database region mentioning the solid */
	mk_comb1(fdmodel, "r.NMG", "s.NMG", 1);

	wdb_close(fdmodel);
    }


    return 0;
}
Esempio n. 6
0
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;
}
Esempio n. 7
0
/**
 * Makes a deep copy of a NMG model structure.
 */
struct model *
nmg_clone_model(const struct model *original)
{
    struct model           *ret;
    void *              *structArray;
    const struct nmgregion *originalRegion;
    struct bn_tol           tolerance;

    NMG_CK_MODEL(original);

    structArray = (void **)bu_calloc(original->maxindex, sizeof(void *), "nmg_clone_model() structArray");

    ret = nmg_mm();
    ret->index    = original->index;
    ret->maxindex = original->maxindex;

    structArray[ret->index] = ret;

    tolerance.magic   = BN_TOL_MAGIC;
    tolerance.dist    = 0.0005;
    tolerance.dist_sq = tolerance.dist * tolerance.dist;
    tolerance.perp    = 1e-6;
    tolerance.para    = 1 - tolerance.perp;

    for (BU_LIST_FOR(originalRegion, nmgregion, &original->r_hd)) {
	struct nmgregion *newRegion = (struct nmgregion *)structArray[originalRegion->index];

	if (newRegion == NULL) {
	    const struct shell *originalShell;

	    newRegion = nmg_construct_region(ret, originalRegion, structArray);

	    for (BU_LIST_FOR(originalShell, shell, &originalRegion->s_hd)) {
		struct shell *newShell = (struct shell *)structArray[originalShell->index];

		if (newShell == NULL)
		    newShell = nmg_construct_shell(newRegion, originalShell, structArray);

		BU_LIST_INSERT(&newRegion->s_hd, &newShell->l);
	    }

	    BU_LIST_INSERT(&ret->r_hd, &newRegion->l);
	}
    }

    bu_free(structArray, "nmg_clone_model() structArray");

    return ret;
}
Esempio n. 8
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;
}
/*
 *	Convert an ascii nmg description into a BRL-CAD data base.
 */
static int
ascii_to_brlcad(FILE *fpin, struct rt_wdb *fpout, char *reg_name, char *grp_name)
{
    struct model	*m;
    struct nmgregion	*r;
    struct bn_tol	tol;
    struct shell	*s;
    vect_t		Ext;
    struct faceuse *fu;
    plane_t		pl;

    VSETALL(Ext, 0.);

    m = nmg_mm();		/* Make nmg model. */
    r = nmg_mrsv(m);	/* Make region, empty shell, vertex */
    s = BU_LIST_FIRST(shell, &r->s_hd);
    descr_to_nmg(s, fpin, Ext);	/* Convert ascii description to nmg. */

    /* Copied from proc-db/nmgmodel.c */
    tol.magic = BN_TOL_MAGIC;
    tol.dist = 0.01;
    tol.dist_sq = tol.dist * tol.dist;
    tol.perp = 0.001;
    tol.para = 0.999;

    /* Associate the face geometry. */
    fu = BU_LIST_FIRST( faceuse, &s->fu_hd );
    if (nmg_loop_plane_area(BU_LIST_FIRST(loopuse, &fu->lu_hd), pl) < 0.0)
	return -1;
    else
	nmg_face_g( fu, pl );

    if (!NEAR_ZERO(MAGNITUDE(Ext), 0.001))
	nmg_extrude_face(BU_LIST_FIRST(faceuse, &s->fu_hd), Ext, &tol);

    nmg_region_a(r, &tol);	/* Calculate geometry for region and shell. */

    nmg_fix_normals( s, &tol ); /* insure that faces have outward pointing normals */

    create_brlcad_db(fpout, m, reg_name, grp_name);

    return 0;
}
Esempio n. 10
0
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;
}
Esempio n. 11
0
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;
}
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;
}
/*
 * 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;
}
Esempio n. 14
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);
}
Esempio n. 15
0
/*
 *			M A I N
 */
int
main(int argc, char **argv)
{
    char		*dot, *fig_file;
    register int	c;
    double		percent;
    int size;

    bu_setlinebuf( stderr );

    jack_tree_state = rt_initial_tree_state;	/* struct copy */
    jack_tree_state.ts_tol = &tol;
    jack_tree_state.ts_ttol = &ttol;
    jack_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-6;
    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, "a:dn:p:r:vx:P:X:")) != EOF) {
	switch (c) {
	    case 'a':		/* Absolute tolerance. */
		ttol.abs = atof(bu_optarg);
		break;
	    case 'd':
		debug_plots = 1;
		break;
	    case 'n':		/* Surface normal tolerance. */
		ttol.norm = atof(bu_optarg);
		break;
	    case 'p':		/* Prefix for Jack file names. */
		prefix = 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 'X':
		sscanf( bu_optarg, "%x", (unsigned int *)&rt_g.NMG_debug );
		NMG_debug = rt_g.NMG_debug;
		break;
	    default:
		bu_exit(1, usage, argv[0]);
		break;
	}
    }

    if (bu_optind+1 >= argc) {
	bu_exit(1, usage, argv[0]);
    }

    /* 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, "ERROR: Unable to open geometry database (%s)\n", argv[0]);
    }
    if ( db_dirbuild( dbip ) ) {
	bu_exit(1, "db_dirbuild failed\n" );
    }

    /* Create .fig file name and open it. */
    size = sizeof(prefix) + sizeof(argv[0] + 4);
    fig_file = bu_malloc(size, "st");
    /* Ignore leading path name. */
    if ((dot = strrchr(argv[0], '/')) != (char *)NULL) {
	if (prefix) {
	    snprintf(fig_file, size, "%s%s", prefix, 1+dot);
	} else {
	    snprintf(fig_file, size, "%s", 1+dot);
	}
    } else {
	if (prefix)
	    snprintf(fig_file, size, "%s%s", prefix, argv[0]);
	else
	    snprintf(fig_file, size, "%s", argv[0]);
    }

    /* Get rid of any file name extension (probably .g). */
    if ((dot = strrchr(fig_file, '.')) != (char *)NULL)
	*dot = '\0';
    bu_strlcat(fig_file, ".fig", size);	/* Add required Jack suffix. */

    if ((fp_fig = fopen(fig_file, "wb")) == NULL)
	perror(fig_file);
    fprintf(fp_fig, "figure {\n");
    bu_vls_init(&base_seg);		/* .fig figure file's main segment. */

    /* Walk indicated tree(s).  Each region will be output separately */
    (void)db_walk_tree(dbip, argc-1, (const char **)(argv+1),
		       1,			/* ncpu */
		       &jack_tree_state,
		       0,			/* take all regions */
		       do_region_end,
		       nmg_booltree_leaf_tess,
		       (genptr_t)NULL);	/* in librt/nmg_bool.c */

    fprintf(fp_fig, "\troot=%s_seg.base;\n", bu_vls_addr(&base_seg));
    fprintf(fp_fig, "}\n");
    fclose(fp_fig);
    bu_free(fig_file, "st");
    bu_vls_free(&base_seg);

    percent = 0;
    if (regions_tried>0)  percent = ((double)regions_done * 100) / regions_tried;
    printf("Tried %d regions, %d converted successfully.  %g%%\n",
	   regions_tried, regions_done, percent);

    return 0;
}
Esempio n. 16
0
/*
 *			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;
}
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;
}
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;
}
Esempio n. 19
0
int
main(int argc, char *argv[])
{
    size_t i;
    int ret;
    int c;
    double percent;
    char copy_buffer[CP_BUF_SIZE] = {0};
    struct directory *dp;

    bu_setprogname(argv[0]);
    bu_setlinebuf(stderr);

    bu_log("%s", brlcad_ident("BRL-CAD to IGES Translator"));
    bu_log("Please direct bug reports to <*****@*****.**>\n\n");

    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 = 0.0005;
    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 */

    rt_init_resource(&rt_uniresource, 0, NULL);

    prog_name = argv[0];

    /* Get command line arguments. */
    while ((c = bu_getopt(argc, argv, "ftsmd:a:n:o:p:r:vx:P:X:")) != -1) {
	switch (c) {
	    case 'f':		/* Select facetized output */
		mode = FACET_MODE;
		multi_file = 0;
		break;
	    case 't':
		mode = TRIMMED_SURF_MODE;
		multi_file = 0;
		break;
	    case 'm':		/* multi-file mode */
		multi_file = 1;
		mode = TRIMMED_SURF_MODE;
		break;
	    case 's':		/* Select NURB output */
		do_nurbs = 1;
		break;
	    case 'v':
		verbose++;
		break;
	    case 'a':		/* Absolute tolerance. */
		ttol.abs = atof(bu_optarg);
		break;
	    case 'r':		/* Relative tolerance. */
		ttol.rel = atof(bu_optarg);
		break;
	    case 'n':		/* Surface normal tolerance. */
		ttol.norm = atof(bu_optarg);
		break;
	    case 'd':		/* distance tolerance */
		tol.dist = atof(bu_optarg);
		tol.dist_sq = tol.dist * tol.dist;
		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 'o':		/* Output file name. */
		output_file = bu_optarg;
		break;
	    case 'P':
		ncpu = atoi(bu_optarg);
		break;
	    default:
		usage(argv[0]);
		break;
	}
    }

    if (bu_optind+1 >= argc) {
	usage(argv[0]);
    }

    /* Open BRL-CAD database */
    argc -= bu_optind;
    argv += bu_optind;
    db_name = argv[0];
    if ((DBIP = db_open(db_name, DB_OPEN_READONLY)) == DBI_NULL) {
	perror("g-iges");
	bu_exit(1, "ERROR: unable to open geometry database file (%s)\n", db_name);
    }

    /* Scan the database */
    if (db_dirbuild(DBIP)) {
	bu_exit(1, "db_dirbuild failed\n");
    }

    if (!multi_file) {
	/* let the IGES routines know the selected tolerances and the database pointer */
	iges_init(&tol, &ttol, verbose, DBIP);

	/* Open the output file */
	if (output_file == NULL)
	    fp_dir = stdout;
	else {
	    if ((fp_dir = fopen(output_file, "wb")) == NULL) {
		perror(output_file);
		bu_exit(1, "Cannot open output file: %s\n", output_file);
	    }
	}

	/* 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");
	}

	/* Write start and global sections of the IGES file */
	w_start_global(fp_dir, fp_param, argv[0], prog_name, output_file, __DATE__, brlcad_version());
    } else {
	if (!bu_file_directory(output_file)) {
	    bu_exit(1, "-o option must provide a directory, %s is not a directory\n", output_file);
	}
    }

    /* Count object references */
/* for (i = 1; i < argc; i++) {
   dp = db_lookup(DBIP, argv[i], 1);
   db_functree(DBIP, dp, count_refs, 0, NULL);
   }	*/

    /* tree tops must have independent status, so we need to remember them */
    independent = (argv+1);
    no_of_indeps = (size_t)argc-1;

    if (mode == FACET_MODE) {
	/* Walk indicated tree(s).  Each region will be output
	 * as a single manifold solid BREP object */

	ret = db_walk_tree(DBIP, argc-1, (const char **)(argv+1),
			   ncpu,
			   &tree_state,
			   0,			/* take all regions */
			   do_nmg_region_end,
			   nmg_booltree_leaf_tess,
			   (void *)NULL);	/* in librt/nmg_bool.c */

	if (ret)
	    bu_exit(1, "g-iges: Could not facetize anything!");

	if (!multi_file) {
	    /* Now walk the same trees again, but only output groups */
	    for (i = 1; i < (size_t)argc; i++) {
		char *ptr;

		ptr = strrchr(argv[i], '/');
		if (ptr != NULL) {
		    ptr++;
		} else {
		    ptr = argv[i];
		}
		dp = db_lookup(DBIP, ptr, 1);
		if (!dp) {
		    bu_log("WARNING: Unable to locate %s in %s\n, skipping\n", ptr, db_name);
		    continue;
		}
		db_functree(DBIP, dp, csg_comb_func, 0, &rt_uniresource, NULL);
	    }
	}
    } else if (mode == CSG_MODE) {
	/* Walk indicated tree(s). Each combination and solid will be output
	 * as a CSG object, unless there is no IGES equivalent (then the
	 * solid will be tessellated and output as a BREP object) */

	for (i = 1; i < (size_t)argc; i++) {
	    dp = db_lookup(DBIP, argv[i], 1);
	    if (!dp) {
		bu_log("WARNING: Unable to locate %s in %s\n, skipping\n", argv[i], db_name);
		continue;
	    }
	    db_functree(DBIP, dp, csg_comb_func, csg_leaf_func, &rt_uniresource, NULL);
	}
    } else if (mode == TRIMMED_SURF_MODE) {
	/* Walk the indicated tree(s). Each region is output as a collection
	 * of trimmed NURBS */

	ret = db_walk_tree(DBIP, argc-1, (const char **)(argv+1),
			   ncpu,
			   &tree_state,
			   0,			/* take all regions */
			   do_nmg_region_end,
			   nmg_booltree_leaf_tess,
			   (void *)NULL);	/* in librt/nmg_bool.c */

	if (ret)
	    bu_exit(1, "g-iges: Could not facetize anything!");

    }

    if (!multi_file) {
	/* 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);
    }

    /* Print some statistics */
    Print_stats(stdout);

    /* report on the success rate for facetizing regions */
    if (mode == FACET_MODE || mode == TRIMMED_SURF_MODE) {
	percent = 0;
	if (regions_tried>0) percent = ((double)regions_done * 100) / regions_tried;
	bu_log("Tried %d regions, %d converted to nmg's successfully.  %g%%\n",
	       regions_tried, regions_done, percent);
    }

    /* re-iterate warnings */
    if (scale_error || solid_error || comb_error)
	bu_log("WARNING: the IGES file produced has errors:\n");
    if (scale_error)
	bu_log("\t%d scaled objects found, written to IGES file without being scaled\n", scale_error);
    if (solid_error)
	bu_log("\t%d solids were not converted to IGES format\n", solid_error);
    if (comb_error)
	bu_log("\t%d combinations were not converted to IGES format\n", comb_error);

    return 0;
}
Esempio n. 20
0
HIDDEN void
get_ctria3(void)
{
    int pid;
    int g1, g2, g3;
    int gin1, gin2, gin3;
    point_t pt1, pt2, pt3;
    struct vertex **v[3];
    struct faceuse *fu;
    struct shell *s;
    struct pshell *psh;
    int pid_index=0;

    pid = atoi(curr_rec[2]);

    pid_index = get_pid_index(pid);

    g1 = atoi(curr_rec[3]);

    g2 = atoi(curr_rec[4]);

    g3 = atoi(curr_rec[5]);

    gin1 = get_gridi(g1);
    gin2 = get_gridi(g2);
    gin3 = get_gridi(g3);

    v[0] = &g_pts[gin1].v[pid_index];
    v[1] = &g_pts[gin2].v[pid_index];
    v[2] = &g_pts[gin3].v[pid_index];

    VSCALE(pt1, g_pts[gin1].pt, conv[units]);
    VSCALE(pt2, g_pts[gin2].pt, conv[units]);
    VSCALE(pt3, g_pts[gin3].pt, conv[units]);

    if (!nmg_model && !pid) {
	struct nmgregion *r;

	nmg_model = nmg_mm();
	r = nmg_mrsv(nmg_model);
	nmg_shell = BU_LIST_FIRST(shell, &r->s_hd);
    }

    if (!pid)
	s = nmg_shell;
    else {
	int found=0;

	/* find pshell entry for this pid */
	for (BU_LIST_FOR(psh, pshell, &pshell_head.l)) {
	    if (psh->pid == pid) {
		found = 1;
		break;
	    }
	}

	if (!found) {
	    bu_log("Cannot find PSHELL entry for a CTRIA3 element (ignoring)!\n");
	    write_fields();
	    return;
	}

	if (psh->s)
	    s = psh->s;
	else {
	    struct model *m;
	    struct nmgregion *r;

	    m = nmg_mm();
	    r = nmg_mrsv(m);
	    s = BU_LIST_FIRST(shell, &r->s_hd);
	    psh->s = s;
	}
    }

    fu = nmg_cmface(s, v, 3);

    if (!g_pts[gin1].v[pid_index]->vg_p)
	nmg_vertex_gv(g_pts[gin1].v[pid_index], pt1);
    if (!g_pts[gin2].v[pid_index]->vg_p)
	nmg_vertex_gv(g_pts[gin2].v[pid_index], pt2);
    if (!g_pts[gin3].v[pid_index]->vg_p)
	nmg_vertex_gv(g_pts[gin3].v[pid_index], pt3);

    nmg_calc_face_g(fu);
}
Esempio n. 21
0
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;
}
Esempio n. 22
0
/*
 * 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 */
}
Esempio n. 23
0
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;
}
Esempio n. 24
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);
}
Esempio n. 25
0
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;
}
Esempio n. 26
0
int
main(int argc, char **argv) 			/* really has no arguments */

{
    struct nmgregion *r;
    char * id_name = "BRL-CAD t-NURBS NMG Example";
    char * tea_name = "UtahTeapot";
    char * uplot_name = "teapot.pl";
    struct bu_list vhead;
    FILE *fp;
    int i;

    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;

    BU_LIST_INIT( &rt_g.rtg_vlfree );

    outfp = wdb_fopen( "tea_nmg.g" );

    rt_g.debug |= DEBUG_ALLRAYS;	/* Cause core dumps on bu_bomb(), but no extra messages */

    while ((i=bu_getopt(argc, argv, "d")) != EOF) {
        switch (i) {
        case 'd' :
            rt_g.debug |= DEBUG_MEM | DEBUG_MEM_FULL;
            break;
        default	:
            (void)fprintf(stderr,
                          "Usage: %s [-d] > database.g\n", *argv);
            return(-1);
        }
    }

    mk_id( outfp, id_name);

    m = nmg_mm();
    NMG_CK_MODEL( m );
    r = nmg_mrsv( m );
    NMG_CK_REGION( r );
    s = BU_LIST_FIRST( shell, &r->s_hd );
    NMG_CK_SHELL( s );

    /* Step through each patch and create a NMG TNURB face
     * representing the patch then dump them out.
     */

    for ( i = 0; i < PATCH_COUNT; i++)
    {
        dump_patch( patches[i] );
    }

    /* Connect up the coincident vertexuses and edges */
    (void)nmg_model_fuse( m, &tol );

    /* write NMG to output file */
    (void)mk_nmg( outfp, tea_name, m );
    wdb_close(outfp);

    /* Make a vlist drawing of the model */
    BU_LIST_INIT( &vhead );
    nmg_m_to_vlist( &vhead, m, 0 );

    /* Make a UNIX plot file from this vlist */
    if ( (fp=fopen( uplot_name, "w" )) == NULL )
    {
        bu_log( "Cannot open plot file: %s\n", uplot_name );
        perror( "teapot_nmg" );
    }
    else
        rt_vlist_to_uplot( fp, &vhead );

    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;
}
Esempio n. 28
0
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;


}
Esempio n. 29
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;
}
Esempio n. 30
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;
}