コード例 #1
0
/*
 * The only reason for this to be broken out is that
 * 2 separate locations in db_functree() call it.
 */
void
db_functree_subtree(struct db_i *dbip,
		    union tree *tp,
		    void (*comb_func) (struct db_i *, struct directory *, void *),
		    void (*leaf_func) (struct db_i *, struct directory *, void *),
		    struct resource *resp,
		    void *client_data)
{
    struct directory *dp;

    if (!tp)
	return;

    RT_CHECK_DBI(dbip);
    RT_CK_TREE(tp);
    if (resp) {
	RT_CK_RESOURCE(resp);
    }

    switch (tp->tr_op) {

	case OP_DB_LEAF:
	    if ((dp=db_lookup(dbip, tp->tr_l.tl_name, LOOKUP_NOISY)) == RT_DIR_NULL)
		return;
	    db_functree(dbip, dp, comb_func, leaf_func, resp, client_data);
	    break;

	case OP_UNION:
	case OP_INTERSECT:
	case OP_SUBTRACT:
	case OP_XOR:
	    db_functree_subtree(dbip, tp->tr_b.tb_left, comb_func, leaf_func, resp, client_data);
	    db_functree_subtree(dbip, tp->tr_b.tb_right, comb_func, leaf_func, resp, client_data);
	    break;
	default:
	    bu_log("db_functree_subtree: unrecognized operator %d\n", tp->tr_op);
	    bu_bomb("db_functree_subtree: unrecognized operator\n");
    }
}
コード例 #2
0
/**
 * A generic traversal function.
 */
void
db_traverse_subtree(union tree *tp,
		    void (*traverse_func) (struct directory *, struct db_traverse *),
		    struct db_traverse *dtp)
{
    struct directory *dp;

    if (!tp)
	return;

    RT_CK_DB_TRAVERSE(dtp);
    RT_CHECK_DBI(dtp->dbip);
    RT_CK_TREE(tp);
    if (dtp->resp) {
	RT_CK_RESOURCE(dtp->resp);
    }

    switch (tp->tr_op) {

	case OP_DB_LEAF:
	    if ((dp=db_lookup(dtp->dbip, tp->tr_l.tl_name, LOOKUP_NOISY)) == RT_DIR_NULL)
		return;
	    traverse_func(dp, dtp);
	    break;

	case OP_UNION:
	case OP_INTERSECT:
	case OP_SUBTRACT:
	case OP_XOR:
	    db_traverse_subtree(tp->tr_b.tb_left, traverse_func, dtp);
	    db_traverse_subtree(tp->tr_b.tb_right, traverse_func, dtp);
	    break;
	default:
	    bu_log("db_functree_subtree: unrecognized operator %d\n", tp->tr_op);
	    bu_bomb("db_functree_subtree: unrecognized operator\n");
    }
}
コード例 #3
0
int
ged_redraw(struct ged *gedp, int argc, const char *argv[])
{
    int ret;
    struct display_list *gdlp;

    GED_CHECK_DATABASE_OPEN(gedp, GED_ERROR);
    GED_CHECK_DRAWABLE(gedp, GED_ERROR);
    GED_CHECK_ARGC_GT_0(gedp, argc, GED_ERROR);
    RT_CHECK_DBI(gedp->ged_wdbp->dbip);

    bu_vls_trunc(gedp->ged_result_str, 0);

    if (argc == 1) {
	/* redraw everything */
	for (BU_LIST_FOR(gdlp, display_list, gedp->ged_gdp->gd_headDisplay))
	{
	    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: redraw failure\n", argv[0]);
		return GED_ERROR;
	    }
	}
    } else {
コード例 #4
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 */
}
コード例 #5
0
ファイル: population.c プロジェクト: cogitokat/brlcad
void
pop_gop(int gop, char *parent1_id, char *parent2_id, char *child1_id, char *child2_id, struct db_i *dbi_p, struct db_i *dbi_c, struct resource *resp)
{
    struct rt_db_internal in1, in2;
    struct rt_comb_internal *parent1;
    struct rt_comb_internal *parent2;
    struct directory *dp;
    union tree *cpoint, **cross_parent;
    struct node *add;
    int i = 0;
    struct node *chosen_node;
    int rand_node;

    RT_CHECK_DBI( dbi_p );
    RT_CHECK_DBI( dbi_c );
    RT_CK_RESOURCE( resp );


    crossover_point = (union tree *)NULL;
    crossover_parent = (union tree **)NULL;
    node = (struct node*)NULL;

    if ( !rt_db_lookup_internal(dbi_p, parent1_id, &dp, &in1, LOOKUP_NOISY, &rt_uniresource))
	bu_exit(EXIT_FAILURE, "Failed to read parent1");
    shape_number =num_nodes= 0;
    parent1 = (struct rt_comb_internal *)in1.idb_ptr;
    mutate = 0;
    switch (gop) {
	case REPRODUCE:
	    pop_functree(dbi_p, dbi_c, parent1->tree, resp, child1_id);
	    break;
	case CROSSOVER:

	    crossover = 1;
	    /*load other parent */
	    if ( !rt_db_lookup_internal(dbi_p, parent2_id, &dp, &in2, LOOKUP_NOISY, resp))
		bu_exit(EXIT_FAILURE, "Failed to read parent2");
	    parent2 = (struct rt_comb_internal *)in2.idb_ptr;

	    BU_ALLOC(node, struct node);
	    BU_LIST_INIT(&node->l);
	    chosen_node = NULL;

	    do{
		num_nodes = 0;
		crossover_parent = &parent1->tree;
		crossover_node = (int)(pop_rand() * db_count_tree_nodes(parent1->tree, 0));
		node_idx = 0;
		pop_functree(dbi_p, dbi_c, parent1->tree, resp, NULL);
		cross_parent = crossover_parent;
		cpoint = crossover_point;


		crossover_op = crossover_point->tr_op;
#define MASK (OP_UNION | OP_XOR | OP_SUBTRACT|OP_INTERSECT)
		if (crossover_op & MASK)crossover_op = MASK;
		crossover_node = db_count_tree_nodes(crossover_point, 0);
		if (pop_find_nodes(parent2->tree) == crossover_node) {
		    BU_ALLOC(add, struct node);
		    add->s_parent = &parent2->tree;
		    add->s_child = parent2->tree;
		    BU_LIST_INSERT(&node->l, &add->l);
		    ++num_nodes;
		}
		if (num_nodes > 0) {
		    rand_node = (int)(pop_rand() * num_nodes);
		    for (add=BU_LIST_FIRST(node, &node->l);BU_LIST_NOT_HEAD(add, &node->l) && chosen_node == NULL; add=BU_LIST_PNEXT(node, add)) {
			if (i++ == rand_node) {
			    chosen_node = add;
			    /* break cleanly...? */
			}
		    }
		}
	    }while(chosen_node == NULL);


	    /* cross trees */
	    *cross_parent = chosen_node->s_child;
	    *chosen_node->s_parent =cpoint;

	    while (BU_LIST_WHILE(add, node, &node->l)) {
		BU_LIST_DEQUEUE(&add->l);
		bu_free(add, "node");
	    }
	    bu_free(node, "node");


	    crossover = 0;

	    /*duplicate shapes held in trees*/
	    pop_functree(dbi_p, dbi_c, parent1->tree, resp, child1_id);
	    shape_number = 0;
	    pop_functree(dbi_p, dbi_c, parent2->tree, resp, child2_id);


	    if ((dp = db_diradd(dbi_c, child2_id, -1, 0, dp->d_flags, (genptr_t)&dp->d_minor_type)) == RT_DIR_NULL)
		bu_exit(EXIT_FAILURE, "Failed to add new individual to child database");
	    if (rt_db_put_internal(dp, dbi_c, &in2, resp) < 0)
		bu_exit(EXIT_FAILURE, "Database write failure");
	    rt_db_free_internal(&in2);

	    break;
	case MUTATE:
	    crossover_parent = &parent1->tree;
	    crossover_node = (int)(pop_rand() * db_count_tree_nodes(parent1->tree, 0));
	    node_idx = 0;
	    mutate = 1;
	    pop_functree(dbi_p, dbi_c, parent1->tree, resp, child1_id);
	    mutate = 0;
	    break;
	    /*
	    //random node to mutate
	    n = (int)(pop_rand() * db_count_tree_nodes(parent1->tree, 0));
	    s_parent = &parent1->tree;
	    s_node = n;
	    node = 0;
	    //find node
	    pop_functree(dbi_p, dbi_c, parent1->tree, resp, NULL);
	    */


	default:
	    bu_exit(EXIT_FAILURE, "illegal genetic operator\nfailed to execute genetic op");
    }


    if ((dp=db_diradd(dbi_c, child1_id, -1, 0, dp->d_flags, (genptr_t)&dp->d_minor_type)) == RT_DIR_NULL) {
	bu_exit(EXIT_FAILURE, "Failed to add new individual to child database");
    }
    if (rt_db_put_internal(dp, dbi_c,  &in1, resp) < 0)
      bu_exit(EXIT_FAILURE, "Database write failure");
    rt_db_free_internal(&in1);
}
コード例 #6
0
int
ged_facetize(struct ged *gedp, int argc, const char *argv[])
{
    int i;
    int c;
    char *newname;
    struct rt_db_internal intern;
    struct directory *dp;
    int failed;
    int nmg_use_tnurbs = 0;
    struct db_tree_state init_state;
    struct db_i *dbip;
    union tree *facetize_tree;
    struct model *nmg_model;

    static const char *usage = "[ [-P] | [-n] [-t] [-T] ] new_obj old_obj [old_obj2 old_obj3 ...]";

    /* static due to jumping */
    static int triangulate;
    static int make_bot;
    static int marching_cube;
    static int screened_poisson;

    GED_CHECK_DATABASE_OPEN(gedp, GED_ERROR);
    GED_CHECK_READ_ONLY(gedp, GED_ERROR);
    GED_CHECK_ARGC_GT_0(gedp, argc, GED_ERROR);

    /* initialize result */
    bu_vls_trunc(gedp->ged_result_str, 0);

    /* must be wanting help */
    if (argc == 1) {
	bu_vls_printf(gedp->ged_result_str, "Usage: %s %s", argv[0], usage);
	return GED_HELP;
    }

    if (argc < 3) {
	bu_vls_printf(gedp->ged_result_str, "Usage: %s %s", argv[0], usage);
	return GED_ERROR;
    }

    dbip = gedp->ged_wdbp->dbip;
    RT_CHECK_DBI(dbip);

    db_init_db_tree_state(&init_state, dbip, gedp->ged_wdbp->wdb_resp);

    /* Establish tolerances */
    init_state.ts_ttol = &gedp->ged_wdbp->wdb_ttol;
    init_state.ts_tol = &gedp->ged_wdbp->wdb_tol;

    /* Initial values for options, must be reset each time */
    marching_cube = 0;
    screened_poisson = 0;
    triangulate = 0;
    make_bot = 1;

    /* Parse options. */
    bu_optind = 1;		/* re-init bu_getopt() */
    while ((c=bu_getopt(argc, (char * const *)argv, "mntTP")) != -1) {
	switch (c) {
	    case 'm':
		marching_cube = triangulate = 1;
		/* no break, marching cubes assumes nmg for now */
	    case 'n':
		make_bot = 0;
		break;
	    case 'P':
		screened_poisson = 1;
		triangulate = 1;
		make_bot = 1;
		break;
	    case 'T':
		triangulate = 1;
		break;
	    case 't':
		nmg_use_tnurbs = 1;
		break;
	    default: {
		bu_vls_printf(gedp->ged_result_str, "Usage: %s %s", argv[0], usage);
		return GED_ERROR;
	    }
	}
    }
    argc -= bu_optind;
    argv += bu_optind;
    if (argc < 0) {
	bu_vls_printf(gedp->ged_result_str, "facetize: missing argument\n");
	return GED_ERROR;
    }

    if (screened_poisson && (marching_cube || !make_bot || nmg_use_tnurbs)) {
	bu_vls_printf(gedp->ged_result_str, "Usage: %s %s", argv[0], usage);
	return GED_ERROR;
    }

    newname = (char *)argv[0];
    argv++;
    argc--;
    if (argc < 0) {
	bu_vls_printf(gedp->ged_result_str, "facetize: missing argument\n");
	return GED_ERROR;
    }

    if (db_lookup(dbip, newname, LOOKUP_QUIET) != RT_DIR_NULL) {
	bu_vls_printf(gedp->ged_result_str, "error: solid '%s' already exists, aborting\n", newname);
	return GED_ERROR;
    }

    if (screened_poisson) {

	struct rt_bot_internal *bot;

	BU_ALLOC(bot, struct rt_bot_internal);
	bot->magic = RT_BOT_INTERNAL_MAGIC;
	bot->mode = RT_BOT_SOLID;
	bot->orientation = RT_BOT_UNORIENTED;
	bot->thickness = (fastf_t *)NULL;
	bot->face_mode = (struct bu_bitv *)NULL;

	/* TODO - generate point cloud, then mesh - need to see the input points for debugging */
	(void)rt_generate_mesh(&(bot->faces), (int *)&(bot->num_faces), (point_t **)&(bot->vertices), (int *)&(bot->num_vertices),
		dbip, argv[0], 15);

	/* Export BOT as a new solid */
	RT_DB_INTERNAL_INIT(&intern);
	intern.idb_major_type = DB5_MAJORTYPE_BRLCAD;
	intern.idb_type = ID_BOT;
	intern.idb_meth = &OBJ[ID_BOT];
	intern.idb_ptr = (void *) bot;

    } else {

	bu_vls_printf(gedp->ged_result_str,
		"facetize:  tessellating primitives with tolerances a=%g, r=%g, n=%g\n",
		gedp->ged_wdbp->wdb_ttol.abs, gedp->ged_wdbp->wdb_ttol.rel, gedp->ged_wdbp->wdb_ttol.norm);

	facetize_tree = (union tree *)0;
	nmg_model = nmg_mm();
	init_state.ts_m = &nmg_model;

	i = db_walk_tree(dbip, argc, (const char **)argv,
		1,
		&init_state,
		0,			/* take all regions */
		facetize_region_end,
		nmg_use_tnurbs ?
		nmg_booltree_leaf_tnurb :
		nmg_booltree_leaf_tess,
		(void *)&facetize_tree
		);


	if (i < 0) {
	    bu_vls_printf(gedp->ged_result_str, "facetize: error in db_walk_tree()\n");
	    /* Destroy NMG */
	    nmg_km(nmg_model);
	    return GED_ERROR;
	}

	if (facetize_tree) {
	    /* Now, evaluate the boolean tree into ONE region */
	    bu_vls_printf(gedp->ged_result_str, "facetize:  evaluating boolean expressions\n");

	    if (!BU_SETJUMP) {
		/* try */
		failed = nmg_boolean(facetize_tree, nmg_model, &gedp->ged_wdbp->wdb_tol, &rt_uniresource);
	    } else {
		/* catch */
		BU_UNSETJUMP;
		bu_vls_printf(gedp->ged_result_str, "WARNING: facetization failed!!!\n");
		db_free_tree(facetize_tree, &rt_uniresource);
		facetize_tree = (union tree *)NULL;
		nmg_km(nmg_model);
		nmg_model = (struct model *)NULL;
		return GED_ERROR;
	    } BU_UNSETJUMP;

	} else
	    failed = 1;

	if (failed) {
	    bu_vls_printf(gedp->ged_result_str, "facetize:  no resulting region, aborting\n");
	    db_free_tree(facetize_tree, &rt_uniresource);
	    facetize_tree = (union tree *)NULL;
	    nmg_km(nmg_model);
	    nmg_model = (struct model *)NULL;
	    return GED_ERROR;
	}
	/* New region remains part of this nmg "model" */
	NMG_CK_REGION(facetize_tree->tr_d.td_r);
	bu_vls_printf(gedp->ged_result_str, "facetize:  %s\n", facetize_tree->tr_d.td_name);

	/* Triangulate model, if requested */
	if (triangulate && !make_bot) {
	    bu_vls_printf(gedp->ged_result_str, "facetize:  triangulating resulting object\n");
	    if (!BU_SETJUMP) {
		/* try */
		if (marching_cube == 1)
		    nmg_triangulate_model_mc(nmg_model, &gedp->ged_wdbp->wdb_tol);
		else
		    nmg_triangulate_model(nmg_model, &gedp->ged_wdbp->wdb_tol);
	    } else {
		/* catch */
		BU_UNSETJUMP;
		bu_vls_printf(gedp->ged_result_str, "WARNING: triangulation failed!!!\n");
		db_free_tree(facetize_tree, &rt_uniresource);
		facetize_tree = (union tree *)NULL;
		nmg_km(nmg_model);
		nmg_model = (struct model *)NULL;
		return GED_ERROR;
	    } BU_UNSETJUMP;
	}

	if (make_bot) {
	    struct rt_bot_internal *bot;
	    struct nmgregion *r;
	    struct shell *s;

	    bu_vls_printf(gedp->ged_result_str, "facetize:  converting to BOT format\n");

	    /* WTF, FIXME: this is only dumping the first shell of the first region */

	    r = BU_LIST_FIRST(nmgregion, &nmg_model->r_hd);
	    if (r && BU_LIST_NEXT(nmgregion, &r->l) !=  (struct nmgregion *)&nmg_model->r_hd)
		bu_vls_printf(gedp->ged_result_str, "WARNING: model has more than one region, only facetizing the first\n");

	    s = BU_LIST_FIRST(shell, &r->s_hd);
	    if (s && BU_LIST_NEXT(shell, &s->l) != (struct shell *)&r->s_hd)
		bu_vls_printf(gedp->ged_result_str, "WARNING: model has more than one shell, only facetizing the first\n");

	    if (!BU_SETJUMP) {
		/* try */
		bot = (struct rt_bot_internal *)nmg_bot(s, &gedp->ged_wdbp->wdb_tol);
	    } else {
		/* catch */
		BU_UNSETJUMP;
		bu_vls_printf(gedp->ged_result_str, "WARNING: conversion to BOT failed!\n");
		db_free_tree(facetize_tree, &rt_uniresource);
		facetize_tree = (union tree *)NULL;
		nmg_km(nmg_model);
		nmg_model = (struct model *)NULL;
		return GED_ERROR;
	    } BU_UNSETJUMP;

	    nmg_km(nmg_model);
	    nmg_model = (struct model *)NULL;

	    /* Export BOT as a new solid */
	    RT_DB_INTERNAL_INIT(&intern);
	    intern.idb_major_type = DB5_MAJORTYPE_BRLCAD;
	    intern.idb_type = ID_BOT;
	    intern.idb_meth = &OBJ[ID_BOT];
	    intern.idb_ptr = (void *) bot;
	} else {

	    bu_vls_printf(gedp->ged_result_str, "facetize:  converting NMG to database format\n");

	    /* Export NMG as a new solid */
	    RT_DB_INTERNAL_INIT(&intern);
	    intern.idb_major_type = DB5_MAJORTYPE_BRLCAD;
	    intern.idb_type = ID_NMG;
	    intern.idb_meth = &OBJ[ID_NMG];
	    intern.idb_ptr = (void *)nmg_model;
	    nmg_model = (struct model *)NULL;
	}

    }

    dp=db_diradd(dbip, newname, RT_DIR_PHONY_ADDR, 0, RT_DIR_SOLID, (void *)&intern.idb_type);
    if (dp == RT_DIR_NULL) {
	bu_vls_printf(gedp->ged_result_str, "Cannot add %s to directory\n", newname);
	return GED_ERROR;
    }

    if (rt_db_put_internal(dp, dbip, &intern, &rt_uniresource) < 0) {
	bu_vls_printf(gedp->ged_result_str, "Failed to write %s to database\n", newname);
	rt_db_free_internal(&intern);
	return GED_ERROR;
    }

    if (!screened_poisson) {
	facetize_tree->tr_d.td_r = (struct nmgregion *)NULL;

	/* Free boolean tree, and the regions in it */
	db_free_tree(facetize_tree, &rt_uniresource);
	facetize_tree = (union tree *)NULL;
    }

    return GED_OK;
}