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