Example #1
0
/**
 * Called from nmg_eval_shell
 *
 * Located here because definition of nmg_bool_state is local to this
 * module.
 */
HIDDEN void
nmg_eval_plot(struct nmg_bool_state *bs, int num)
{
    FILE *fp;
    char fname[128];
    int do_plot = 0;
    int do_anim = 0;

    if (RTG.NMG_debug & DEBUG_BOOLEVAL && RTG.NMG_debug & DEBUG_PLOTEM)
	do_plot = 1;
    if (RTG.NMG_debug & DEBUG_PL_ANIM) do_anim = 1;

    if (!do_plot && !do_anim) return;

    BN_CK_TOL(bs->bs_tol);

    if (do_plot) {
	sprintf(fname, "nmg_eval%d.plot3", num);
	if ((fp = fopen(fname, "wb")) == NULL) {
	    perror(fname);
	    return;
	}
	bu_log("Plotting %s\n", fname);

	nmg_pl_s(fp, bs->bs_dest);
	nmg_pl_s(fp, bs->bs_src);

	fclose(fp);
    }

    if (do_anim) {
	struct bn_vlblock *vbp;

	vbp = rt_vlblock_init();

	nmg_vlblock_s(vbp, bs->bs_dest, 0);
	nmg_vlblock_s(vbp, bs->bs_src, 0);

	/* Cause animation of boolean operation as it proceeds! */
	if (nmg_vlblock_anim_upcall) {
	    /* if requested, delay 1/4 second */
	    /* need to cast nmg_vlblock_anim_upcall pointer for actual use as a function */
	    void (*cfp)(struct bn_vlblock *, int, int);
	    cfp = (void (*)(struct bn_vlblock *, int, int))nmg_vlblock_anim_upcall;
	    cfp(vbp,
		(RTG.NMG_debug&DEBUG_PL_SLOW) ? 250000 : 0,
		0);
	} else {
	    bu_log("null nmg_vlblock_anim_upcall, no animation\n");
	}
	rt_vlblock_free(vbp);
    }
}
int
ged_brep(struct ged *gedp, int argc, const char *argv[])
{
    struct bn_vlblock*vbp;
    const char *solid_name;
    static const char *usage = "brep <obj> [command|brepname|suffix] ";
    struct directory *ndp;
    struct rt_db_internal intern;
    struct rt_brep_internal* bi;
    struct brep_specific* bs;
    struct soltab *stp;
    char commtag[64];
    char namebuf[64];
    int i, j, real_flag, valid_command, ret;
    const char *commands[] = {"info", "plot", "translate", "intersect", "csg", "u", "i", "-"};
    int num_commands = (int)(sizeof(commands) / sizeof(const char *));
    db_op_t op = DB_OP_NULL;

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

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

    /* must be wanting help */
    if (argc < 2) {
	bu_vls_printf(gedp->ged_result_str, "Usage: %s\n\t%s\n", argv[0], usage);
	bu_vls_printf(gedp->ged_result_str, "commands:\n");
	bu_vls_printf(gedp->ged_result_str, "\tvalid          - report on validity of specific BREP\n");
	bu_vls_printf(gedp->ged_result_str, "\tinfo           - return count information for specific BREP\n");
	bu_vls_printf(gedp->ged_result_str, "\tinfo S [index] - return information for specific BREP 'surface'\n");
	bu_vls_printf(gedp->ged_result_str, "\tinfo F [index] - return information for specific BREP 'face'\n");
	bu_vls_printf(gedp->ged_result_str, "\tplot           - plot entire BREP\n");
	bu_vls_printf(gedp->ged_result_str, "\tplot S [index] - plot specific BREP 'surface'\n");
	bu_vls_printf(gedp->ged_result_str, "\tplot F [index] - plot specific BREP 'face'\n");
	bu_vls_printf(gedp->ged_result_str, "\tcsg            - convert BREP to implicit primitive CSG tree\n");
	bu_vls_printf(gedp->ged_result_str, "\ttranslate SCV index i j dx dy dz - translate a surface control vertex\n");
	bu_vls_printf(gedp->ged_result_str, "\tintersect <obj2> <i> <j> [PP|PC|PS|CC|CS|SS] - BREP intersections\n");
	bu_vls_printf(gedp->ged_result_str, "\tu|i|- <obj2> <output>     - BREP boolean evaluations\n");
	bu_vls_printf(gedp->ged_result_str, "\t[brepname]                - convert the non-BREP object to BREP form\n");
	bu_vls_printf(gedp->ged_result_str, "\t --no-evaluation [suffix] - convert non-BREP comb to unevaluated BREP form\n");
	return GED_HELP;
    }

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

    solid_name = argv[1];
    if ((ndp = db_lookup(gedp->ged_wdbp->dbip,  solid_name, LOOKUP_NOISY)) == RT_DIR_NULL) {
	bu_vls_printf(gedp->ged_result_str, "Error: %s is not a solid or does not exist in database", solid_name);
	return GED_ERROR;
    } else {
	real_flag = (ndp->d_addr == RT_DIR_PHONY_ADDR) ? 0 : 1;
    }

    if (!real_flag) {
	/* solid doesn't exist - don't kill */
	bu_vls_printf(gedp->ged_result_str, "Error: %s is not a real solid", solid_name);
	return GED_OK;
    }

    GED_DB_GET_INTERNAL(gedp, &intern, ndp, bn_mat_identity, &rt_uniresource, GED_ERROR);


    RT_CK_DB_INTERNAL(&intern);
    bi = (struct rt_brep_internal*)intern.idb_ptr;

    if (BU_STR_EQUAL(argv[2], "valid")) {
	int valid = rt_brep_valid(&intern, gedp->ged_result_str);
	return (valid) ? GED_OK : GED_ERROR;
    }

    if (BU_STR_EQUAL(argv[2], "intersect")) {
	/* handle surface-surface intersection */
	struct rt_db_internal intern2;

	/* we need exactly 6 or 7 arguments */
	if (argc != 6 && argc != 7) {
	    bu_vls_printf(gedp->ged_result_str, "There should be 6 or 7 arguments for intersection.\n");
	    bu_vls_printf(gedp->ged_result_str, "See the usage for help.\n");
	    return GED_ERROR;
	}

	/* get the other solid */
	if ((ndp = db_lookup(gedp->ged_wdbp->dbip,  argv[3], LOOKUP_NOISY)) == RT_DIR_NULL) {
	    bu_vls_printf(gedp->ged_result_str, "Error: %s is not a solid or does not exist in database", argv[3]);
	    return GED_ERROR;
	} else {
	    real_flag = (ndp->d_addr == RT_DIR_PHONY_ADDR) ? 0 : 1;
	}

	if (!real_flag) {
	    /* solid doesn't exist - don't kill */
	    bu_vls_printf(gedp->ged_result_str, "Error: %s is not a real solid", argv[3]);
	    return GED_OK;
	}

	GED_DB_GET_INTERNAL(gedp, &intern2, ndp, bn_mat_identity, &rt_uniresource, GED_ERROR);

	i = atoi(argv[4]);
	j = atoi(argv[5]);
	vbp = rt_vlblock_init();

	if (argc == 6 || BU_STR_EQUAL(argv[6], "SS")) {
	    brep_intersect_surface_surface(&intern, &intern2, i, j, vbp);
	} else if (BU_STR_EQUAL(argv[6], "PP")) {
	    brep_intersect_point_point(&intern, &intern2, i, j);
	} else if (BU_STR_EQUAL(argv[6], "PC")) {
	    brep_intersect_point_curve(&intern, &intern2, i, j);
	} else if (BU_STR_EQUAL(argv[6], "PS")) {
	    brep_intersect_point_surface(&intern, &intern2, i, j);
	} else if (BU_STR_EQUAL(argv[6], "CC")) {
	    brep_intersect_curve_curve(&intern, &intern2, i, j);
	} else if (BU_STR_EQUAL(argv[6], "CS")) {
	    brep_intersect_curve_surface(&intern, &intern2, i, j);
	} else {
	    bu_vls_printf(gedp->ged_result_str, "Invalid intersection type %s.\n", argv[6]);
	}

	_ged_cvt_vlblock_to_solids(gedp, vbp, namebuf, 0);
	bn_vlblock_free(vbp);
	vbp = (struct bn_vlblock *)NULL;

	rt_db_free_internal(&intern);
	rt_db_free_internal(&intern2);
	return GED_OK;
    }

    if (BU_STR_EQUAL(argv[2], "csg")) {
	/* Call csg conversion routine */
	struct bu_vls bname_csg;
	bu_vls_init(&bname_csg);
	bu_vls_sprintf(&bname_csg, "csg_%s", solid_name);
	if (db_lookup(gedp->ged_wdbp->dbip, bu_vls_addr(&bname_csg), LOOKUP_QUIET) != RT_DIR_NULL) {
	    bu_vls_printf(gedp->ged_result_str, "%s already exists.", bu_vls_addr(&bname_csg));
	    bu_vls_free(&bname_csg);
	    return GED_OK;
	}
	bu_vls_free(&bname_csg);
	return _ged_brep_to_csg(gedp, argv[1]);
    }

    /* make sure arg isn't --no-evaluate */
    if (argc > 2 && argv[2][1] != '-') {
	op = db_str2op(argv[2]);
    }

    if (op != DB_OP_NULL) {
	/* test booleans on brep.
	 * u: union, i: intersect, -: diff, x: xor
	 */
	struct rt_db_internal intern2, intern_res;
	struct rt_brep_internal *bip;

	if (argc != 5) {
	    bu_vls_printf(gedp->ged_result_str, "Error: There should be exactly 5 params.\n");
	    return GED_ERROR;
	}

	/* get the other solid */
	if ((ndp = db_lookup(gedp->ged_wdbp->dbip,  argv[3], LOOKUP_NOISY)) == RT_DIR_NULL) {
	    bu_vls_printf(gedp->ged_result_str, "Error: %s is not a solid or does not exist in database", argv[3]);
	    return GED_ERROR;
	} else {
	    real_flag = (ndp->d_addr == RT_DIR_PHONY_ADDR) ? 0 : 1;
	}

	if (!real_flag) {
	    /* solid doesn't exist - don't kill */
	    bu_vls_printf(gedp->ged_result_str, "Error: %s is not a real solid", argv[3]);
	    return GED_OK;
	}

	GED_DB_GET_INTERNAL(gedp, &intern2, ndp, bn_mat_identity, &rt_uniresource, GED_ERROR);

	rt_brep_boolean(&intern_res, &intern, &intern2, op);
	bip = (struct rt_brep_internal*)intern_res.idb_ptr;
	mk_brep(gedp->ged_wdbp, argv[4], bip->brep);
	rt_db_free_internal(&intern);
	rt_db_free_internal(&intern2);
	rt_db_free_internal(&intern_res);
	return GED_OK;
    }

    if (BU_STR_EQUAL(argv[2], "selection")) {
	ret = selection_command(gedp, &intern, argc, argv);
	if (BU_STR_EQUAL(argv[3], "translate") && ret == 0) {
	    GED_DB_PUT_INTERNAL(gedp, ndp, &intern, &rt_uniresource, GED_ERROR);
	}
	rt_db_free_internal(&intern);

	return ret;
    }

    if (!RT_BREP_TEST_MAGIC(bi)) {
	/* The solid is not in brep form. Covert it to brep. */

	struct bu_vls bname, suffix;
	int no_evaluation = 0;

	bu_vls_init(&bname);
	bu_vls_init(&suffix);

	if (argc == 2) {
	    /* brep obj */
	    bu_vls_sprintf(&bname, "%s_brep", solid_name);
	    bu_vls_sprintf(&suffix, "_brep");
	} else if (BU_STR_EQUAL(argv[2], "--no-evaluation")) {
	    no_evaluation = 1;
	    if (argc == 3) {
		/* brep obj --no-evaluation */
		bu_vls_sprintf(&bname, "%s_brep", solid_name);
		bu_vls_sprintf(&suffix, "_brep");
	    } else if (argc == 4) {
		/* brep obj --no-evaluation suffix */
		bu_vls_sprintf(&bname, argv[3]);
		bu_vls_sprintf(&suffix, argv[3]);
	    }
	} else {
	    /* brep obj brepname/suffix */
	    bu_vls_sprintf(&bname, argv[2]);
	    bu_vls_sprintf(&suffix, argv[2]);
	}

	if (no_evaluation && intern.idb_type == ID_COMBINATION) {
	    struct bu_vls bname_suffix;
	    bu_vls_init(&bname_suffix);
	    bu_vls_sprintf(&bname_suffix, "%s%s", solid_name, bu_vls_addr(&suffix));
	    if (db_lookup(gedp->ged_wdbp->dbip, bu_vls_addr(&bname_suffix), LOOKUP_QUIET) != RT_DIR_NULL) {
		bu_vls_printf(gedp->ged_result_str, "%s already exists.", bu_vls_addr(&bname_suffix));
		bu_vls_free(&bname);
		bu_vls_free(&suffix);
		bu_vls_free(&bname_suffix);
		return GED_OK;
	    }
	    brep_conversion_comb(&intern, bu_vls_addr(&bname_suffix), bu_vls_addr(&suffix), gedp->ged_wdbp, mk_conv2mm);
	    bu_vls_free(&bname_suffix);
	} else {
	    struct rt_db_internal brep_db_internal;
	    ON_Brep* brep;
	    if (db_lookup(gedp->ged_wdbp->dbip, bu_vls_addr(&bname), LOOKUP_QUIET) != RT_DIR_NULL) {
		bu_vls_printf(gedp->ged_result_str, "%s already exists.", bu_vls_addr(&bname));
		bu_vls_free(&bname);
		bu_vls_free(&suffix);
		return GED_OK;
	    }
	    ret = brep_conversion(&intern, &brep_db_internal, gedp->ged_wdbp->dbip);
	    if (ret == -1) {
		bu_vls_printf(gedp->ged_result_str, "%s doesn't have a "
			"brep-conversion function yet. Type: %s", solid_name,
			intern.idb_meth->ft_label);
	    } else if (ret == -2) {
		bu_vls_printf(gedp->ged_result_str, "%s cannot be converted "
			"to brep correctly.", solid_name);
	    } else {
		brep = ((struct rt_brep_internal *)brep_db_internal.idb_ptr)->brep;
		ret = mk_brep(gedp->ged_wdbp, bu_vls_addr(&bname), brep);
		if (ret == 0) {
		    bu_vls_printf(gedp->ged_result_str, "%s is made.", bu_vls_addr(&bname));
		}
		rt_db_free_internal(&brep_db_internal);
	    }
	}
	bu_vls_free(&bname);
	bu_vls_free(&suffix);
	rt_db_free_internal(&intern);
	return GED_OK;
    }

    BU_ALLOC(stp, struct soltab);

    if (argc == 2) {
	bu_vls_printf(gedp->ged_result_str, "Usage: %s %s\n", argv[0], usage);
	bu_vls_printf(gedp->ged_result_str, "\t%s is in brep form, please input a command.", solid_name);
	return GED_HELP;
    }

    valid_command = 0;
    for (i = 0; i < num_commands; ++i) {
	if (BU_STR_EQUAL(argv[2], commands[i])) {
	    valid_command = 1;
	    break;
	}
    }

    if (!valid_command) {
	bu_vls_printf(gedp->ged_result_str, "Usage: %s %s\n", argv[0], usage);
	bu_vls_printf(gedp->ged_result_str, "\t%s is in brep form, please input a command.", solid_name);
	return GED_HELP;
    }

    if ((bs = (struct brep_specific*)stp->st_specific) == NULL) {
	BU_ALLOC(bs, struct brep_specific);
	bs->brep = bi->brep;
	bi->brep = NULL;
	stp->st_specific = (void *)bs;
    }

    vbp = rt_vlblock_init();

    brep_command(gedp->ged_result_str, solid_name, (const struct rt_tess_tol *)&gedp->ged_wdbp->wdb_ttol, &gedp->ged_wdbp->wdb_tol, bs, bi, vbp, argc, argv, commtag);

    if (BU_STR_EQUAL(argv[2], "translate")) {
	bi->brep = bs->brep;
	GED_DB_PUT_INTERNAL(gedp, ndp, &intern, &rt_uniresource, GED_ERROR);
    }

    snprintf(namebuf, 64, "%s%s_", commtag, solid_name);
    _ged_cvt_vlblock_to_solids(gedp, vbp, namebuf, 0);
    bn_vlblock_free(vbp);
    vbp = (struct bn_vlblock *)NULL;

    rt_db_free_internal(&intern);

    return GED_OK;
}
Example #3
0
/*
 * F _ N I R T
 *
 * Invoke nirt with the current view & stuff
 */
int
dgo_nirt_cmd(struct dg_obj *dgop,
	     struct view_obj *vop,
	     int argc,
	     const char **argv)
{
    const char **vp;
    FILE *fp_in;
    FILE *fp_out, *fp_err;
#ifndef _WIN32
    int ret;
    size_t sret;
    int pid, rpid;
    int retcode;
    int pipe_in[2];
    int pipe_out[2];
    int pipe_err[2];
#else
    HANDLE pipe_in[2], pipe_inDup;
    HANDLE pipe_out[2], pipe_outDup;
    HANDLE pipe_err[2], pipe_errDup;
    STARTUPINFO si;
    PROCESS_INFORMATION pi;
    SECURITY_ATTRIBUTES sa;
    char name[1024];
    char line1[2048];
    int rem = 2048;
#endif
    int use_input_orig = 0;
    vect_t center_model;
    vect_t dir;
    vect_t cml;
    int i;
    struct solid *sp;
    char line[RT_MAXLINE];
    char *val;
    struct bu_vls vls = BU_VLS_INIT_ZERO;
    struct bu_vls o_vls = BU_VLS_INIT_ZERO;
    struct bu_vls p_vls = BU_VLS_INIT_ZERO;
    struct bu_vls t_vls = BU_VLS_INIT_ZERO;
    struct bn_vlblock *vbp;
    struct dg_qray_dataList *ndlp;
    struct dg_qray_dataList HeadQRayData;
    int args;

    args = argc + 20 + 2 + dgo_count_tops((struct solid *)&dgop->dgo_headSolid);
    dgop->dgo_rt_cmd = (char **)bu_calloc(args, sizeof(char *), "alloc dgo_rt_cmd");

    vp = (const char **)&dgop->dgo_rt_cmd[0];
    *vp++ = "nirt";

    /* swipe x, y, z off the end if present */
    if (argc > 3) {
	double scan[3];

	if (sscanf(argv[argc-3], "%lf", &scan[X]) == 1 &&
	    sscanf(argv[argc-2], "%lf", &scan[Y]) == 1 &&
	    sscanf(argv[argc-1], "%lf", &scan[Z]) == 1)
	{

	    VMOVE(center_model, scan);
	    use_input_orig = 1;
	    argc -= 3;
	    VSCALE(center_model, center_model, dgop->dgo_wdbp->dbip->dbi_local2base);
	}
    }

    /* Calculate point from which to fire ray */
    if (!use_input_orig) {
	VSET(center_model, -vop->vo_center[MDX],
	     -vop->vo_center[MDY], -vop->vo_center[MDZ]);
    }

    VSCALE(cml, center_model, dgop->dgo_wdbp->dbip->dbi_base2local);
    VMOVEN(dir, vop->vo_rotation + 8, 3);
    VSCALE(dir, dir, -1.0);

    bu_vls_printf(&p_vls, "xyz %lf %lf %lf;",
		  cml[X], cml[Y], cml[Z]);
    bu_vls_printf(&p_vls, "dir %lf %lf %lf; s",
		  dir[X], dir[Y], dir[Z]);

    i = 0;
    if (DG_QRAY_GRAPHICS(dgop)) {

	*vp++ = "-e";
	*vp++ = DG_QRAY_FORMAT_NULL;

	/* first ray ---- returns partitions */
	*vp++ = "-e";
	*vp++ = DG_QRAY_FORMAT_P;

	/* ray start, direction, and 's' command */
	*vp++ = "-e";
	*vp++ = bu_vls_addr(&p_vls);

	/* second ray ---- returns overlaps */
	*vp++ = "-e";
	*vp++ = DG_QRAY_FORMAT_O;

	/* ray start, direction, and 's' command */
	*vp++ = "-e";
	*vp++ = bu_vls_addr(&p_vls);

	if (DG_QRAY_TEXT(dgop)) {
	    char *cp;
	    int count = 0;

	    /* get 'r' format now; prepend its' format string with a newline */
	    val = bu_vls_addr(&dgop->dgo_qray_fmts[0].fmt);

	    /* find first '"' */
	    while (*val != '"' && *val != '\0')
		++val;

	    if (*val == '\0')
		goto done;
	    else
		++val;	    /* skip first '"' */

	    /* find last '"' */
	    cp = (char *)strrchr(val, '"');

	    if (cp != (char *)NULL) /* found it */
		count = cp - val;

	done:
	    if (*val == '\0')
		bu_vls_printf(&o_vls, " fmt r \"\\n\" ");
	    else {
		struct bu_vls tmp = BU_VLS_INIT_ZERO;
		bu_vls_strncpy(&tmp, val, count);
		bu_vls_printf(&o_vls, " fmt r \"\\n%V\" ", &tmp);
		bu_vls_free(&tmp);

		if (count)
		    val += count + 1;
		bu_vls_printf(&o_vls, "%s", val);
	    }

	    i = 1;

	    *vp++ = "-e";
	    *vp++ = bu_vls_addr(&o_vls);
	}
    }

    if (DG_QRAY_TEXT(dgop)) {

	/* load vp with formats for printing */
	for (; dgop->dgo_qray_fmts[i].type != (char)0; ++i)
	    bu_vls_printf(&t_vls, "fmt %c %s; ",
			  dgop->dgo_qray_fmts[i].type,
			  bu_vls_addr(&dgop->dgo_qray_fmts[i].fmt));

	*vp++ = "-e";
	*vp++ = bu_vls_addr(&t_vls);

	/* nirt does not like the trailing ';' */
	bu_vls_trunc(&t_vls, -2);
    }

    /* include nirt script string */
    if (bu_vls_strlen(&dgop->dgo_qray_script)) {
	*vp++ = "-e";
	*vp++ = bu_vls_addr(&dgop->dgo_qray_script);
    }

    *vp++ = "-e";
    *vp++ = bu_vls_addr(&p_vls);

    for (i = 1; i < argc; i++)
	*vp++ = argv[i];
    *vp++ = dgop->dgo_wdbp->dbip->dbi_filename;

    dgop->dgo_rt_cmd_len = (char **)vp - (char **)dgop->dgo_rt_cmd;

    /* Note - dgo_build_tops sets the last vp to (char *)0 */
    dgop->dgo_rt_cmd_len += dgo_build_tops((struct solid *)&dgop->dgo_headSolid,
					   vp,
					   (const char **)&dgop->dgo_rt_cmd[args]);

    if (dgop->dgo_qray_cmd_echo) {
	/* Print out the command we are about to run */
	vp = (const char **)&dgop->dgo_rt_cmd[0];
	while (*vp)
	    Tcl_AppendResult(dgop->interp, *vp++, " ", (char *)NULL);

	Tcl_AppendResult(dgop->interp, "\n", (char *)NULL);
    }

    if (use_input_orig) {
	bu_vls_printf(&vls, "\nFiring from (%lf, %lf, %lf)...\n",
		      center_model[X], center_model[Y], center_model[Z]);
	Tcl_AppendResult(dgop->interp, bu_vls_addr(&vls), (char *)NULL);
	bu_vls_free(&vls);
    } else
	Tcl_AppendResult(dgop->interp, "\nFiring from view center...\n", (char *)NULL);

#ifndef _WIN32
    ret = pipe(pipe_in);
    if (ret < 0)
	perror("pipe");
    ret = pipe(pipe_out);
    if (ret < 0)
	perror("pipe");
    ret = pipe(pipe_err);
    if (ret < 0)
	perror("pipe");
    (void)signal(SIGINT, SIG_IGN);
    if ((pid = fork()) == 0) {
	/* Redirect stdin, stdout, stderr */
	(void)close(0);
	ret = dup(pipe_in[0]);
	if (ret < 0)
	    perror("dup");
	(void)close(1);
	ret = dup(pipe_out[1]);
	if (ret < 0)
	    perror("dup");
	(void)close(2);
	ret = dup(pipe_err[1]);
	if (ret < 0)
	    perror("dup");

	/* close pipes */
	(void)close(pipe_in[0]);
	(void)close(pipe_in[1]);
	(void)close(pipe_out[0]);
	(void)close(pipe_out[1]);
	(void)close(pipe_err[0]);
	(void)close(pipe_err[1]);
	for (i = 3; i < 20; i++)
	    (void)close(i);
	(void)signal(SIGINT, SIG_DFL);
	(void)execvp(dgop->dgo_rt_cmd[0], dgop->dgo_rt_cmd);
	perror (dgop->dgo_rt_cmd[0]);
	exit(16);
    }

    /* use fp_in to feed view info to nirt */
    (void)close(pipe_in[0]);
    fp_in = fdopen(pipe_in[1], "w");

    /* use fp_out to read back the result */
    (void)close(pipe_out[1]);
    fp_out = fdopen(pipe_out[0], "r");

    /* use fp_err to read any error messages */
    (void)close(pipe_err[1]);
    fp_err = fdopen(pipe_err[0], "r");

    /* send quit command to nirt */
    sret = fwrite("q\n", 1, 2, fp_in);
    if (sret != 2)
	bu_log("fwrite failure\n");

    (void)fclose(fp_in);

#else
    memset((void *)&si, 0, sizeof(STARTUPINFO));
    memset((void *)&pi, 0, sizeof(PROCESS_INFORMATION));
    memset((void *)&sa, 0, sizeof(SECURITY_ATTRIBUTES));

    sa.nLength = sizeof(sa);
    sa.bInheritHandle = TRUE;
    sa.lpSecurityDescriptor = NULL;

    /* Create a pipe for the child process's STDOUT. */
    CreatePipe(&pipe_out[0], &pipe_out[1], &sa, 0);

    /* Create noninheritable read handle and close the inheritable read handle. */
    DuplicateHandle(GetCurrentProcess(), pipe_out[0],
		    GetCurrentProcess(),  &pipe_outDup ,
		    0,  FALSE,
		    DUPLICATE_SAME_ACCESS);
    CloseHandle(pipe_out[0]);

    /* Create a pipe for the child process's STDERR. */
    CreatePipe(&pipe_err[0], &pipe_err[1], &sa, 0);

    /* Create noninheritable read handle and close the inheritable read handle. */
    DuplicateHandle(GetCurrentProcess(), pipe_err[0],
		    GetCurrentProcess(),  &pipe_errDup ,
		    0,  FALSE,
		    DUPLICATE_SAME_ACCESS);
    CloseHandle(pipe_err[0]);

    /* The steps for redirecting child process's STDIN:
     *     1.  Save current STDIN, to be restored later.
     *     2.  Create anonymous pipe to be STDIN for child process.
     *     3.  Set STDIN of the parent to be the read handle to the
     *         pipe, so it is inherited by the child process.
     *     4.  Create a noninheritable duplicate of the write handle,
     *         and close the inheritable write handle.
     */

    /* Create a pipe for the child process's STDIN. */
    CreatePipe(&pipe_in[0], &pipe_in[1], &sa, 0);

    /* Duplicate the write handle to the pipe so it is not inherited. */
    DuplicateHandle(GetCurrentProcess(), pipe_in[1],
		    GetCurrentProcess(), &pipe_inDup,
		    0, FALSE,                  /* not inherited */
		    DUPLICATE_SAME_ACCESS);
    CloseHandle(pipe_in[1]);

    si.cb = sizeof(STARTUPINFO);
    si.lpReserved = NULL;
    si.lpReserved2 = NULL;
    si.cbReserved2 = 0;
    si.lpDesktop = NULL;
    si.dwFlags = STARTF_USESTDHANDLES | STARTF_USESHOWWINDOW;
    si.hStdInput   = pipe_in[0];
    si.hStdOutput  = pipe_out[1];
    si.hStdError   = pipe_err[1];
    si.wShowWindow = SW_HIDE;

    snprintf(line1, rem, "%s ", dgop->dgo_rt_cmd[0]);
    rem -= (int)strlen(line1) - 1;

    for (i = 1; i < dgop->dgo_rt_cmd_len; i++) {
	/* skip commands */
	if (strstr(dgop->dgo_rt_cmd[i], "-e") != NULL)
	    ++i;
	else {
	    /* append other arguments (i.e. options, file and obj(s)) */
	    snprintf(name, 1024, "\"%s\" ", dgop->dgo_rt_cmd[i]);
	    if (rem - strlen(name) < 1) {
		bu_log("Ran out of buffer space!");
		bu_free(dgop->dgo_rt_cmd, "free dgo_rt_cmd");
		dgop->dgo_rt_cmd = NULL;
		return TCL_ERROR;
	    }
	    bu_strlcat(line1, name, sizeof(line1));
	    rem -= (int)strlen(name);
	}
    }

    CreateProcess(NULL, line1, NULL, NULL, TRUE,
		  DETACHED_PROCESS, NULL, NULL,
		  &si, &pi);

    /* use fp_in to feed view info to nirt */
    CloseHandle(pipe_in[0]);
    fp_in = _fdopen(_open_osfhandle((intptr_t)pipe_inDup, _O_TEXT), "wb");
    setmode(fileno(fp_in), O_BINARY);

    /* send commands down the pipe */
    for (i = 1; i < dgop->dgo_rt_cmd_len-2; i++)
	if (strstr(dgop->dgo_rt_cmd[i], "-e") != NULL)
	    fprintf(fp_in, "%s\n", dgop->dgo_rt_cmd[++i]);

    /* use fp_out to read back the result */
    CloseHandle(pipe_out[1]);
    fp_out = _fdopen(_open_osfhandle((intptr_t)pipe_outDup, _O_TEXT), "rb");
    setmode(fileno(fp_out), O_BINARY);

    /* use fp_err to read any error messages */
    CloseHandle(pipe_err[1]);
    fp_err = _fdopen(_open_osfhandle((intptr_t)pipe_errDup, _O_TEXT), "rb");
    setmode(fileno(fp_err), O_BINARY);

    /* send quit command to nirt */
    fwrite("q\n", 1, 2, fp_in);
    (void)fclose(fp_in);

#endif

    bu_vls_free(&p_vls);   /* use to form "partition" part of nirt command above */
    if (DG_QRAY_GRAPHICS(dgop)) {
	double scan[4];

	if (DG_QRAY_TEXT(dgop))
	    bu_vls_free(&o_vls); /* used to form "overlap" part of nirt command above */

	BU_LIST_INIT(&HeadQRayData.l);

	/* handle partitions */
	while (bu_fgets(line, RT_MAXLINE, fp_out) != (char *)NULL) {
	    if (line[0] == '\n') {
		Tcl_AppendResult(dgop->interp, line+1, (char *)NULL);
		break;
	    }

	    BU_ALLOC(ndlp, struct dg_qray_dataList);
	    BU_LIST_APPEND(HeadQRayData.l.back, &ndlp->l);

	    if (sscanf(line, "%le %le %le %le",
		       &scan[0], &scan[1], &scan[2], &scan[3]) != 4)
		break;
	    ndlp->x_in = scan[0];
	    ndlp->y_in = scan[1];
	    ndlp->z_in = scan[2];
	    ndlp->los = scan[3];
	}

	vbp = rt_vlblock_init();
	dgo_qray_data_to_vlist(dgop, vbp, &HeadQRayData, dir, 0);
	bu_list_free(&HeadQRayData.l);
	dgo_cvt_vlblock_to_solids(dgop, vbp, bu_vls_addr(&dgop->dgo_qray_basename), 0);
	rt_vlblock_free(vbp);

	/* handle overlaps */
	while (bu_fgets(line, RT_MAXLINE, fp_out) != (char *)NULL) {
	    if (line[0] == '\n') {
		Tcl_AppendResult(dgop->interp, line+1, (char *)NULL);
		break;
	    }

	    BU_ALLOC(ndlp, struct dg_qray_dataList);
	    BU_LIST_APPEND(HeadQRayData.l.back, &ndlp->l);

	    if (sscanf(line, "%le %le %le %le",
		       &scan[0], &scan[1], &scan[2], &scan[3]) != 4)
		break;
	    ndlp->x_in = scan[0];
	    ndlp->y_in = scan[1];
	    ndlp->z_in = scan[2];
	    ndlp->los = scan[3];
	}
	vbp = rt_vlblock_init();
	dgo_qray_data_to_vlist(dgop, vbp, &HeadQRayData, dir, 1);
	bu_list_free(&HeadQRayData.l);
	dgo_cvt_vlblock_to_solids(dgop, vbp, bu_vls_addr(&dgop->dgo_qray_basename), 0);
	rt_vlblock_free(vbp);
    }

    /*
     * Notify observers, if any, before generating textual output since
     * such an act (observer notification) wipes out whatever gets stuffed
     * into the result.
     */
    dgo_notify(dgop);

    if (DG_QRAY_TEXT(dgop)) {
	bu_vls_free(&t_vls);

	while (bu_fgets(line, RT_MAXLINE, fp_out) != (char *)NULL)
	    Tcl_AppendResult(dgop->interp, line, (char *)NULL);
    }

    (void)fclose(fp_out);

    while (bu_fgets(line, RT_MAXLINE, fp_err) != (char *)NULL)
	Tcl_AppendResult(dgop->interp, line, (char *)NULL);
    (void)fclose(fp_err);


#ifndef _WIN32

    /* Wait for program to finish */
    while ((rpid = wait(&retcode)) != pid && rpid != -1)
	;	/* NULL */

    if (retcode != 0)
	pr_wait_status(dgop->interp, retcode);
#else
    /* Wait for program to finish */
    WaitForSingleObject(pi.hProcess, INFINITE);

#endif

    FOR_ALL_SOLIDS(sp, &dgop->dgo_headSolid)
	sp->s_wflag = DOWN;

    bu_free(dgop->dgo_rt_cmd, "free dgo_rt_cmd");
    dgop->dgo_rt_cmd = NULL;

    return TCL_OK;
}
Example #4
0
static size_t
show_dangling_edges(struct ged *gedp, const uint32_t *magic_p, const char *name, int out_type)
{
    FILE *plotfp = NULL;
    const char *manifolds = NULL;
    const struct edgeuse *eur;
    int done;
    point_t pt1, pt2;
    size_t i, cnt;
    struct bn_vlblock *vbp = NULL;
    struct bu_list *vhead = NULL;
    struct bu_ptbl faces;
    struct bu_vls plot_file_name = BU_VLS_INIT_ZERO;
    struct edgeuse *eu = NULL;
    struct face *fp = NULL;
    struct faceuse *fu, *fu1, *fu2;
    struct faceuse *newfu = NULL;
    struct loopuse *lu = NULL;

    /* out_type: 0 = none, 1 = show, 2 = plot */
    if (out_type < 0 || out_type > 2) {
	bu_log("Internal error, open edge test failed.\n");
	return 0;
    }

    if (out_type == 1) {
	vbp = rt_vlblock_init();
	vhead = rt_vlblock_find(vbp, 0xFF, 0xFF, 0x00);
    }

    bu_ptbl_init(&faces, 64, "faces buffer");
    nmg_face_tabulate(&faces, magic_p);

    cnt = 0;
    for (i = 0; i < (size_t)BU_PTBL_END(&faces) ; i++) {
	fp = (struct face *)BU_PTBL_GET(&faces, i);
	NMG_CK_FACE(fp);
	fu = fu1 = fp->fu_p;
	NMG_CK_FACEUSE(fu1);
	fu2 = fp->fu_p->fumate_p;
	NMG_CK_FACEUSE(fu2);
	done = 0;
	while (!done) {
	    NMG_CK_FACEUSE(fu);
	    for (BU_LIST_FOR(lu, loopuse, &fu->lu_hd)) {
		NMG_CK_LOOPUSE(lu);
		if (BU_LIST_FIRST_MAGIC(&lu->down_hd) == NMG_EDGEUSE_MAGIC) {
		    for (BU_LIST_FOR(eu, edgeuse, &lu->down_hd)) {
			NMG_CK_EDGEUSE(eu);
			eur = nmg_radial_face_edge_in_shell(eu);
			newfu = eur->up.lu_p->up.fu_p;
			while (manifolds &&
			       NMG_MANIFOLDS(manifolds, newfu) &
			       NMG_2MANIFOLD &&
			       eur != eu->eumate_p) {
			    eur = nmg_radial_face_edge_in_shell(eur->eumate_p);
			    newfu = eur->up.lu_p->up.fu_p;
			}
			if (eur == eu->eumate_p) {
			    VMOVE(pt1, eu->vu_p->v_p->vg_p->coord);
			    VMOVE(pt2, eu->eumate_p->vu_p->v_p->vg_p->coord);
			    if (out_type == 1) {
				BN_ADD_VLIST(vbp->free_vlist_hd, vhead, pt1, BN_VLIST_LINE_MOVE);
				BN_ADD_VLIST(vbp->free_vlist_hd, vhead, pt2, BN_VLIST_LINE_DRAW);
			    } else if (out_type == 2) {
				if (!plotfp) {
				    bu_vls_sprintf(&plot_file_name, "%s.%p.pl", name, (void *)magic_p);
				    if ((plotfp = fopen(bu_vls_addr(&plot_file_name), "wb")) == (FILE *)NULL) {
					bu_vls_free(&plot_file_name);
					bu_log("Error, unable to create plot file (%s), open edge test failed.\n",
					       bu_vls_addr(&plot_file_name));
					return 0;
				    }
				}
				pdv_3line(plotfp, pt1, pt2);
			    }
			    cnt++;
			}
		    }
		}
	    }
	    if (fu == fu1) fu = fu2;
	    if (fu == fu2) done = 1;
	};

    }

    if (out_type == 1) {
	/* Add overlay */
	_ged_cvt_vlblock_to_solids(gedp, vbp, (char *)name, 0);
	rt_vlblock_free(vbp);
	bu_log("Showing open edges...\n");
    } else if (out_type == 2) {
	if (plotfp) {
	    (void)fclose(plotfp);
	    bu_log("Wrote plot file (%s)\n", bu_vls_addr(&plot_file_name));
	    bu_vls_free(&plot_file_name);
	}
    }
    bu_ptbl_free(&faces);

    return cnt;
}
/*
 * 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 */
}