Exemplo n.º 1
0
HIDDEN int
extract_format_prefix(struct bu_vls *format, const char *input)
{
    struct bu_vls wformat = BU_VLS_INIT_ZERO;
    char *colon_pos = NULL;
    char *inputcpy = NULL;
    if (UNLIKELY(!input)) return 0;
    inputcpy = bu_strdup(input);
    colon_pos = strchr(inputcpy, ':');
    if (colon_pos) {
	int ret = 0;
	bu_vls_sprintf(&wformat, "%s", input);
	bu_vls_trunc(&wformat, -1 * strlen(colon_pos));
	if (bu_vls_strlen(&wformat) > 0) {
	    ret = 1;
	    if (format) bu_vls_sprintf(format, "%s", bu_vls_addr(&wformat));
	}
	bu_vls_free(&wformat);
	if (inputcpy) bu_free(inputcpy, "input copy");
	return ret;
    } else {
	if (inputcpy) bu_free(inputcpy, "input copy");
	return 0;
    }
    /* Shouldn't get here */
    return 0;
}
Exemplo n.º 2
0
HIDDEN int
extract_path(struct bu_vls *path, const char *input)
{
    int ret = 0;
    struct bu_vls wpath = BU_VLS_INIT_ZERO;
    char *colon_pos = NULL;
    char *inputcpy = NULL;
    if (UNLIKELY(!input)) return 0;
    inputcpy = bu_strdup(input);
    colon_pos = strchr(inputcpy, ':');
    if (colon_pos) {
	bu_vls_sprintf(&wpath, "%s", input);
	bu_vls_nibble(&wpath, strlen(input) - strlen(colon_pos) + 1);
	if (path && bu_vls_strlen(&wpath) > 0) {
	    ret = 1;
	    bu_vls_sprintf(path, "%s", bu_vls_addr(&wpath));
	}
	bu_vls_free(&wpath);
    } else {
	if (path) bu_vls_sprintf(path, "%s", input);
	ret = 1;
    }
    if (inputcpy) bu_free(inputcpy, "input copy");
    if (path && !(bu_vls_strlen(path) > 0)) return 0;
    return ret;
}
Exemplo n.º 3
0
static int
isst_load_g(ClientData UNUSED(clientData), Tcl_Interp *interp, int objc,
	    Tcl_Obj *const *objv)
{
    struct isst_s *isst;
    char **argv;
    int argc;
    double az, el;
    struct bu_vls tclstr = BU_VLS_INIT_ZERO;
    vect_t vec;
    Togl   *togl;

    if (objc < 4) {
	Tcl_WrongNumArgs(interp, 1, objv, "load_g pathname object");
	return TCL_ERROR;
    }

    if (Togl_GetToglFromObj(interp, objv[1], &togl) != TCL_OK) {
	return TCL_ERROR;
    }

    isst = (struct isst_s *) Togl_GetClientData(togl);

    argv = (char **)malloc(sizeof(char *) * (strlen(Tcl_GetString(objv[3])) + 1));	/* allocate way too much. */
    argc = bu_argv_from_string(argv, strlen(Tcl_GetString(objv[3])), Tcl_GetString(objv[3]));

    load_g(isst->tie, Tcl_GetString(objv[2]), argc, (const char **)argv, &(isst->meshes));
    free(argv);

    VSETALL(isst->camera.pos, isst->tie->radius);
    VMOVE(isst->camera.focus, isst->tie->mid);
    VMOVE(isst->camera_pos_init, isst->camera.pos);
    VMOVE(isst->camera_focus_init, isst->camera.focus);

    /* Set the initial az and el values in Tcl/Tk */
    VSUB2(vec, isst->camera.pos, isst->camera.focus);
    VUNITIZE(vec);
    AZEL_FROM_V3DIR(az, el, vec);
    az = az * -DEG2RAD;
    el = el * -DEG2RAD;
    bu_vls_sprintf(&tclstr, "%f", az);
    Tcl_SetVar(interp, "az", bu_vls_addr(&tclstr), 0);
    bu_vls_sprintf(&tclstr, "%f", el);
    Tcl_SetVar(interp, "el", bu_vls_addr(&tclstr), 0);
    bu_vls_free(&tclstr);

    render_phong_init(&isst->camera.render, NULL);

    isst->ogl = 1;
    isst->w = Togl_Width(togl);
    isst->h = Togl_Height(togl);

    resize_isst(isst);

    isst->t1 = bu_gettime();
    isst->t2 = bu_gettime();

    return TCL_OK;
}
Exemplo n.º 4
0
static int
list_geometry(ClientData UNUSED(clientData), Tcl_Interp *interp, int objc, Tcl_Obj *const *objv)
{
    static struct db_i *dbip;
    struct directory *dp;
    int i;
    struct bu_vls tclstr = BU_VLS_INIT_ZERO;

    if (objc < 3) {
	Tcl_WrongNumArgs(interp, 1, objv, "file varname");
	return TCL_ERROR;
    }

    if ((dbip = db_open(Tcl_GetString(objv[1]), "r")) == DBI_NULL) {
	bu_log("Unable to open geometry file (%s)\n", Tcl_GetString(objv[1]));
	return TCL_ERROR;
    }
    db_dirbuild(dbip);
    for (i = 0; i < RT_DBNHASH; i++) {
	for (dp = dbip->dbi_Head[i]; dp != RT_DIR_NULL; dp = dp->d_forw) {
	    if (dp->d_flags & RT_DIR_HIDDEN) continue;
	    bu_vls_sprintf(&tclstr, "set %s [concat $%s [list %s]]", Tcl_GetString(objv[2]), Tcl_GetString(objv[2]), dp->d_namep);
	    Tcl_Eval(interp, bu_vls_addr(&tclstr));
	}
    }
    db_close(dbip);
    bu_vls_free(&tclstr);
    return TCL_OK;
}
Exemplo n.º 5
0
HIDDEN void
reassemble_argstr(struct bu_vls *instr, struct bu_vls *outstr, option::Option *unknowns)
{
    for (option::Option* opt = unknowns; opt; opt = opt->next()) {
	int input_only = 0;
	int output_only = 0;
	char *inputcpy = NULL;
	if (!instr || !outstr) return;
	inputcpy = bu_strdup(opt->name);
	if (!bu_strncmp(inputcpy, "--in-", 5)) input_only = 1;
	if (!bu_strncmp(inputcpy, "--out-", 5)) output_only = 1;
	char *equal_pos = strchr(inputcpy, '=');
	if (equal_pos) {
	    struct bu_vls vopt = BU_VLS_INIT_ZERO;
	    struct bu_vls varg = BU_VLS_INIT_ZERO;
	    bu_vls_sprintf(&vopt, "%s", inputcpy);
	    bu_vls_trunc(&vopt, -1 * strlen(equal_pos));
	    bu_vls_sprintf(&varg, "%s", inputcpy);
	    bu_vls_nibble(&varg, strlen(inputcpy) - strlen(equal_pos) + 1);
	    if (!output_only) {
		(bu_vls_strlen(&vopt) == 1) ? bu_vls_printf(instr, "-%s ", bu_vls_addr(&vopt)) : bu_vls_printf(instr, "%s ", bu_vls_addr(&vopt));
		if (bu_vls_strlen(&varg)) bu_vls_printf(instr, "%s ", bu_vls_addr(&varg));
	    }
	    if (!input_only) {
		(bu_vls_strlen(&vopt) == 1) ? bu_vls_printf(outstr, "-%s ", bu_vls_addr(&vopt)) : bu_vls_printf(outstr, "%s ", bu_vls_addr(&vopt));
		if (bu_vls_strlen(&varg)) bu_vls_printf(outstr, "%s ", bu_vls_addr(&varg));
	    }
	    bu_vls_free(&vopt);
	    bu_vls_free(&varg);
	} else {
	    if (!output_only) {
		(strlen(opt->name) == 1) ? bu_vls_printf(instr, "-%s ", opt->name) : bu_vls_printf(instr, "%s ", opt->name);
		if (opt->arg) bu_vls_printf(instr, "%s ", opt->arg);
	    }
	    if (!input_only) {
		(strlen(opt->name) == 1) ? bu_vls_printf(outstr, "-%s ", opt->name) : bu_vls_printf(outstr, "%s ", opt->name);
		if (opt->arg) bu_vls_printf(outstr, "%s ", opt->arg);
	    }
	}
	bu_free(inputcpy, "input cpy");
    }
}
Exemplo n.º 6
0
HIDDEN int
plot_logfile(struct dm *dmp, const char *filename)
{
    Tcl_Obj *obj;

    obj = Tcl_GetObjResult(dmp->dm_interp);
    if (Tcl_IsShared(obj))
	obj = Tcl_DuplicateObj(obj);

    bu_vls_sprintf(&dmp->dm_log, "%s", filename);
    (void)fflush(((struct plot_vars *)dmp->dm_vars.priv_vars)->up_fp);
    Tcl_AppendStringsToObj(obj, "flushed\n", (char *)NULL);

    Tcl_SetObjResult(dmp->dm_interp, obj);
    return TCL_OK;
}
Exemplo n.º 7
0
void
diff_summarize(struct bu_vls *diff_log, const struct bu_ptbl *results, struct diff_state *state)
{
    int i = 0;
    struct bu_vls added_list = BU_VLS_INIT_ZERO;
    struct bu_vls removed_list = BU_VLS_INIT_ZERO;
    struct bu_vls changed_list = BU_VLS_INIT_ZERO;
    struct bu_vls unchanged_list = BU_VLS_INIT_ZERO;
    struct bu_vls added_tmp = BU_VLS_INIT_ZERO;
    struct bu_vls removed_tmp = BU_VLS_INIT_ZERO;
    struct bu_vls changed_tmp = BU_VLS_INIT_ZERO;
    struct bu_vls unchanged_tmp = BU_VLS_INIT_ZERO;


    if (state->verbosity < 1 || !results)
	return;

    if (state->verbosity == 1) {
	if (state->return_added == 1) bu_vls_sprintf(&added_list, "Added:\n");
	if (state->return_removed == 1) bu_vls_sprintf(&removed_list, "Removed:\n");
	if (state->return_changed == 1) bu_vls_sprintf(&changed_list, "Changed:\n");
	if (state->return_unchanged == 1) bu_vls_sprintf(&unchanged_list, "Unchanged:\n");
    }

    for (i = 0; i < (int)BU_PTBL_LEN(results); i++) {
	int changed = 2;
	struct diff_result *dr = (struct diff_result *)BU_PTBL_GET(results, i);
	if (dr->param_state == DIFF_ADDED && state->return_added == 1) {
	    switch (state->verbosity) {
		case 1:
		    if (strlen(bu_vls_addr(&added_tmp)) + strlen(dr->obj_name) + 2 > 80) {
			bu_vls_printf(&added_list, "%s\n", bu_vls_addr(&added_tmp));
			bu_vls_sprintf(&added_tmp, "%s", dr->obj_name);
		    } else {
			if (strlen(bu_vls_addr(&added_tmp)) > 0) bu_vls_printf(&added_tmp, ", ");
			bu_vls_printf(&added_tmp, "%s", dr->obj_name);
		    }
		    break;
		case 2:
		case 3:
		    bu_vls_printf(diff_log, "A %s\n", dr->obj_name);
		    break;
		case 4:
		    diff_attrs_print(dr, state, diff_log);
		    break;
		default:
		    break;
	    }
	}
	if (dr->param_state == DIFF_REMOVED && state->return_removed == 1) {
	    switch (state->verbosity) {
		case 1:
		    if (strlen(bu_vls_addr(&removed_tmp)) + strlen(dr->obj_name) + 2 > 80) {
			bu_vls_printf(&removed_list, "%s\n", bu_vls_addr(&removed_tmp));
			bu_vls_sprintf(&removed_tmp, "%s", dr->obj_name);
		    } else {
			if (strlen(bu_vls_addr(&removed_tmp)) > 0) bu_vls_printf(&removed_tmp, ", ");
			bu_vls_printf(&removed_tmp, "%s", dr->obj_name);
		    }
		    break;
		case 2:
		case 3:
		    bu_vls_printf(diff_log, "D %s\n", dr->obj_name);
		    break;
		case 4:
		    diff_attrs_print(dr, state, diff_log);
		    break;
		default:
		    break;
	    }
	}

	if ((state->use_params || state->use_attrs) && !(state->use_params && state->use_attrs)) changed--;
	if (state->use_params && ((dr->param_state == DIFF_UNCHANGED) || (dr->param_state == DIFF_UNCHANGED))) changed--;
	if (state->use_attrs && ((dr->attr_state == DIFF_UNCHANGED) || (dr->attr_state == DIFF_UNCHANGED))) changed--;
	if (!changed && state->return_unchanged == 1) {
	    switch (state->verbosity) {
		case 1:
		    if (strlen(bu_vls_addr(&unchanged_tmp)) + strlen(dr->obj_name) + 2 > 80) {
			bu_vls_printf(&unchanged_list, "%s\n", bu_vls_addr(&unchanged_tmp));
			bu_vls_sprintf(&unchanged_tmp, "%s", dr->obj_name);
		    } else {
			if (strlen(bu_vls_addr(&unchanged_tmp)) > 0) bu_vls_printf(&unchanged_tmp, ", ");
			bu_vls_printf(&unchanged_tmp, "%s", dr->obj_name);
		    }
		    break;
		case 2:
		case 3:
		    bu_vls_printf(diff_log, "  %s\n", dr->obj_name);
		    break;
		case 4:
		    diff_attrs_print(dr, state, diff_log);
		    break;
		default:
		    break;
	    }
	}

	changed = 0;
	if (state->use_params) {
	    if (dr->param_state != DIFF_UNCHANGED && dr->param_state != DIFF_EMPTY &&
		    dr->param_state != DIFF_ADDED && dr->param_state != DIFF_REMOVED)
		changed++;
	}
	if (state->use_attrs) {
	    if (dr->attr_state != DIFF_UNCHANGED && dr->attr_state != DIFF_EMPTY &&
		    dr->attr_state != DIFF_ADDED && dr->attr_state != DIFF_REMOVED)
		changed++;
	}
	if (changed && state->return_changed == 1) {
	    switch (state->verbosity) {
		case 1:

		    if (strlen(bu_vls_addr(&changed_tmp)) + strlen(dr->obj_name) + 2 > 80) {
			bu_vls_printf(&changed_list, "%s\n", bu_vls_addr(&changed_tmp));
			bu_vls_sprintf(&changed_tmp, "%s", dr->obj_name);
		    } else {
			if (strlen(bu_vls_addr(&changed_tmp)) > 0) bu_vls_printf(&changed_tmp, ", ");
			bu_vls_printf(&changed_tmp, "%s", dr->obj_name);
		    }
		    break;
		case 2:
		    bu_vls_printf(diff_log, "M %s\n", dr->obj_name);
		    break;
		case 3:
		case 4:
		    diff_attrs_print(dr, state, diff_log);
		    break;
		default:
		    break;
	    }
	}
    }

    if (state->verbosity == 1) {
	bu_vls_printf(&added_list, "%s\n", bu_vls_addr(&added_tmp));
	bu_vls_printf(&removed_list, "%s\n", bu_vls_addr(&removed_tmp));
	bu_vls_printf(&changed_list, "%s\n", bu_vls_addr(&changed_tmp));
	bu_vls_printf(&unchanged_list, "%s\n", bu_vls_addr(&unchanged_tmp));
	if (state->return_added == 1 && strlen(bu_vls_addr(&added_tmp)) > 0)
	    bu_vls_printf(diff_log, "%s\n", bu_vls_addr(&added_list));
	if (state->return_removed == 1 && strlen(bu_vls_addr(&removed_tmp)) > 0)
	    bu_vls_printf(diff_log, "%s\n", bu_vls_addr(&removed_list));
	if (state->return_changed == 1 && strlen(bu_vls_addr(&changed_tmp)) > 0)
	    bu_vls_printf(diff_log, "%s\n", bu_vls_addr(&changed_list));
	if (state->return_unchanged == 1 && strlen(bu_vls_addr(&unchanged_tmp)) > 0)
	    bu_vls_printf(diff_log, "%s\n", bu_vls_addr(&unchanged_list));
    }
}
Exemplo n.º 8
0
/**
 * Add the list of regions in the model to the rigid bodies list in
 * simulation parameters. This function will duplicate the existing
 * regions prefixing "sim_" to the new region and putting them all
 * under a new comb "sim.c". It will skip over any existing regions
 * with "sim_" in the name
 */
int
add_regions(struct ged *gedp, struct simulation_params *sim_params)
{
    struct directory *dp, *ndp;
    char *prefix = "sim_";
    int i;
    struct rigid_body *prev_node = NULL, *current_node;
    struct bu_vls dp_name_vls = BU_VLS_INIT_ZERO;

    /* Kill the existing sim comb */
    sim_kill(gedp, sim_params->sim_comb_name);
    sim_params->num_bodies = 0;

    /* Walk the directory list duplicating all regions only, skip some regions */
    for (i = 0; i < RT_DBNHASH; i++)
	for (dp = gedp->ged_wdbp->dbip->dbi_Head[i]; dp != RT_DIR_NULL; dp = dp->d_forw) {
	    if ((dp->d_flags & RT_DIR_HIDDEN) ||  /* check for hidden comb/prim */
		   !(dp->d_flags & RT_DIR_REGION)     /* check if region */
		) {
		    continue;
	    }

	    if (strstr(dp->d_namep, prefix)) {
		    bu_vls_printf(gedp->ged_result_str, "add_regions: Skipping \"%s\" due to \"%s\" in name\n",
			      dp->d_namep, prefix);
		    continue;
	    }

	    if (BU_STR_EMPTY(dp->d_namep)) {
		    bu_vls_printf(gedp->ged_result_str, "add_regions: Skipping \"%s\" due to empty name\n",
			      dp->d_namep);
		    continue;
	    }

	    /* Duplicate the region */
	    bu_vls_sprintf(&dp_name_vls, "%s%s", prefix, dp->d_namep);

	    sim_kill_copy(gedp, dp, bu_vls_addr(&dp_name_vls));
	    bu_vls_printf(gedp->ged_result_str, "add_regions: Copied \"%s\" to \"%s\"\n", dp->d_namep,
			  bu_vls_addr(&dp_name_vls));

	    /* Get the directory pointer for the object just added */
	    if ((ndp=db_lookup(gedp->ged_wdbp->dbip, bu_vls_addr(&dp_name_vls), LOOKUP_QUIET)) == RT_DIR_NULL) {
		    bu_vls_printf(gedp->ged_result_str, "add_regions: db_lookup(%s) failed", bu_vls_addr(&dp_name_vls));
		    return GED_ERROR;
	    }


	    /* Add to simulation list */
	    BU_ALLOC(current_node, struct rigid_body);
	    current_node->index = sim_params->num_bodies;
	    current_node->rb_namep = bu_strdup(bu_vls_addr(&dp_name_vls));
	    current_node->dp = ndp;
	    current_node->next = NULL;

	    /* Save the internal format as well */
		if (!rt_db_lookup_internal(sim_params->gedp->ged_wdbp->dbip, ndp->d_namep, &ndp,
				&(current_node->intern), LOOKUP_NOISY, &rt_uniresource)) {
			bu_exit(1, "add_regions: ERROR rt_db_lookup_internal(%s) failed to get the internal form",
					ndp->d_namep);
			return GED_ERROR;
		}

	    /* Add physics attribs : one shot get from user */
	    add_physics_attribs(current_node);

	    /* Setup the linked list */
	    if (prev_node == NULL) {
		    /* first node */
		    prev_node = current_node;
		    sim_params->head_node = current_node;
	    } else {
		    /* past 1st node now */
		    prev_node->next = current_node;
		    prev_node = prev_node->next;
	    }

	    /* Add the new region to the simulation result */
	    add_to_comb(gedp, sim_params->sim_comb_name, bu_vls_addr(&dp_name_vls));

	    sim_params->num_bodies++;
	}

    bu_vls_free(&dp_name_vls);

    if(sim_params->num_bodies == 0){
	    bu_vls_printf(gedp->ged_result_str, "add_regions: ERROR No objects were added\n");
	    return GED_ERROR;
    }

    /* Show list of objects to be added to the sim : keep for debugging as of now */
    /* bu_log("add_regions: The following %d regions will participate in the sim : \n", sim_params->num_bodies);
       for (current_node = sim_params->head_node; current_node != NULL; current_node = current_node->next) {
       print_rigid_body(current_node);
       }*/

    return GED_OK;

}
Exemplo n.º 9
0
static int
aerotate(ClientData UNUSED(clientData), Tcl_Interp *interp, int objc, Tcl_Obj *const *objv)
{
    struct isst_s *isst;
    Togl *togl;
    vect_t vec, vecdpos, vecdfoc;
    double x, y;
    double az, el;
    double mag_pos, mag_focus;
    struct bu_vls tclstr = BU_VLS_INIT_ZERO;

    if (objc < 4) {
	Tcl_WrongNumArgs(interp, 1, objv, "pathName x y");
	return TCL_ERROR;
    }

    if (Togl_GetToglFromObj(interp, objv[1], &togl) != TCL_OK)
	return TCL_ERROR;

    isst = (struct isst_s *) Togl_GetClientData(togl);

    if (Tcl_GetDoubleFromObj(interp, objv[2], &x) != TCL_OK)
	return TCL_ERROR;
    if (Tcl_GetDoubleFromObj(interp, objv[3], &y) != TCL_OK)
	return TCL_ERROR;

    mag_pos = DIST_PT_PT(isst->camera.pos, isst->camera_focus_init);

    mag_focus = DIST_PT_PT(isst->camera.focus, isst->camera_focus_init);

    VSUB2(vecdpos, isst->camera_focus_init, isst->camera.pos);
    VUNITIZE(vecdpos);
    AZEL_FROM_V3DIR(az, el, vecdpos);
    az = az * -DEG2RAD - x;
    el = el * -DEG2RAD + y;

    /* clamp to sane values */
    while(az > 2*M_PI) az -= 2*M_PI;
    while(az < 0) az += 2*M_PI;
    if(el>M_PI_2) el=M_PI_2 - 0.001;
    if(el<-M_PI_2) el=-M_PI_2 + 0.001;

    V3DIR_FROM_AZEL(vecdpos, az, el);
    VSCALE(vecdpos, vecdpos, mag_pos);
    VADD2(isst->camera.pos, isst->camera_focus_init, vecdpos);
    if (mag_focus > 0) {
	VSUB2(vecdfoc, isst->camera_focus_init, isst->camera.focus);
	VUNITIZE(vecdfoc);
	AZEL_FROM_V3DIR(az, el, vecdfoc);
	az = az * -DEG2RAD - x;
	el = el * -DEG2RAD + y;

	/* clamp to sane values */
	while(az > 2*M_PI) az -= 2*M_PI;
	while(az < 0) az += 2*M_PI;
	if(el>M_PI_2) el=M_PI_2 - 0.001;
	if(el<-M_PI_2) el=-M_PI_2 + 0.001;

	V3DIR_FROM_AZEL(vecdfoc, az, el);
	VSCALE(vecdfoc, vecdfoc, mag_focus);
	VADD2(isst->camera.focus, isst->camera_focus_init, vecdfoc);
    }
    /* Update the tcl copies of the az/el vars */
    VSUB2(vec, isst->camera.focus, isst->camera.pos);
    VUNITIZE(vec);
    AZEL_FROM_V3DIR(az, el, vec);
    bu_vls_sprintf(&tclstr, "%f", az);
    Tcl_SetVar(interp, "az", bu_vls_addr(&tclstr), 0);
    bu_vls_sprintf(&tclstr, "%f", el);
    Tcl_SetVar(interp, "el", bu_vls_addr(&tclstr), 0);
    bu_vls_free(&tclstr);
    isst->dirty = 1;
    return TCL_OK;
}
Exemplo n.º 10
0
int
main(int argc, char *argv[])
{
    int ret = 0;
    int convert_tops_list = 0;
    struct directory **paths;
    int path_cnt = 0;
    AP203_Contents *sc = new AP203_Contents;

    // process command line arguments
    int c;
    char *output_file = (char *)NULL;
    while ((c = bu_getopt(argc, argv, "o:")) != -1) {
        switch (c) {
        case 'o':
            output_file = bu_optarg;
            break;
        default:
            usage();
            bu_exit(1, NULL);
            break;
        }
    }

    if (bu_optind >= argc || output_file == (char *)NULL) {
        usage();
        bu_exit(1, NULL);
    }

    argc -= bu_optind;
    argv += bu_optind;

    /* check our inputs/outputs */
    if (bu_file_exists(output_file, NULL)) {
        bu_exit(1, "ERROR: refusing to overwrite existing output file:\"%s\". Please remove file or change output file name and try again.", output_file);
    }

    if (!bu_file_exists(argv[0], NULL) && !BU_STR_EQUAL(argv[0], "-")) {
        bu_exit(2, "ERROR: unable to read input \"%s\" .g file", argv[0]);
    }

    if (argc < 2) {
        convert_tops_list = 1;
    }


    std::string iflnm = argv[0];
    std::string oflnm = output_file;

    /* load .g file */
    BRLCADWrapper *dotg  = new BRLCADWrapper();
    if (!dotg) {
        std::cerr << "ERROR: unable to create BRL-CAD instance" << std::endl;
        return 3;
    }
    if (!dotg->load(iflnm)) {
        std::cerr << "ERROR: unable to open BRL-CAD input file [" << oflnm << "]" << std::endl;
        delete dotg;
        return 2;
    }

    struct db_i *dbip = dotg->GetDBIP();
    struct rt_wdb *wdbp = wdb_dbopen(dbip, RT_WDB_TYPE_DB_DISK);

    if (convert_tops_list) {
        /* Need db_update_nref for DB_LS_TOPS to work */
        db_update_nref(dbip, &rt_uniresource);
        path_cnt = db_ls(dbip, DB_LS_TOPS, &paths);
        if (!path_cnt) {
            std::cerr << "ERROR: no objects found in .g file" << "\n" << std::endl;
            delete dotg;
            return 1;
        }
    } else {
        int i = 1;
        paths = (struct directory **)bu_malloc(sizeof(struct directory *) * argc, "dp array");
        while (i < argc) {
            bu_log("%d: %s\n", i, argv[i]);
            struct directory *dp = db_lookup(dbip, argv[i], LOOKUP_QUIET);
            if (dp == RT_DIR_NULL) {
                std::cerr << "ERROR: cannot find " << argv[i] << "\n" << std::endl;
                delete dotg;
                bu_free(paths, "free path memory");
                return 1;
            } else {
                paths[i-1] = dp;
                path_cnt++;
                i++;
            }
        }
        paths[i-1] = RT_DIR_NULL;
    }


    struct bu_vls scratch_string;
    bu_vls_init(&scratch_string);

    Registry *registry = new Registry(SchemaInit);
    InstMgr instance_list;
    STEPfile *sfile = new STEPfile(*registry, instance_list);

    registry->ResetSchemas();
    registry->ResetEntities();

    /* Populate the header instances */
    InstMgr *header_instances = sfile->HeaderInstances();

    /* 1 - Populate File_Name */
    SdaiFile_name * fn = (SdaiFile_name *)sfile->HeaderDefaultFileName();
    bu_vls_sprintf(&scratch_string, "'%s'", output_file);
    fn->name_(bu_vls_addr(&scratch_string));
    fn->time_stamp_("");
    StringAggregate_ptr author_tmp = new StringAggregate;
    author_tmp->AddNode(new StringNode("''"));
    fn->author_(author_tmp);
    StringAggregate_ptr org_tmp = new StringAggregate;
    org_tmp->AddNode(new StringNode("''"));
    fn->organization_(org_tmp);
    fn->preprocessor_version_("'BRL-CAD g-step exporter'");
    fn->originating_system_("''");
    fn->authorization_("''");
    header_instances->Append((SDAI_Application_instance *)fn, completeSE);

    /* 2 - Populate File_Description */
    SdaiFile_description * fd = (SdaiFile_description *)sfile->HeaderDefaultFileDescription();
    StringAggregate_ptr description_tmp = new StringAggregate;
    description_tmp->AddNode(new StringNode("''"));
    fd->description_(description_tmp);
    fd->implementation_level_("'2;1'");
    header_instances->Append((SDAI_Application_instance *)fd, completeSE);

    /* 3 - Populate File_Schema */
    SdaiFile_schema *fs = (SdaiFile_schema *)sfile->HeaderDefaultFileSchema();
    StringAggregate_ptr schema_tmp = new StringAggregate;
    schema_tmp->AddNode(new StringNode("'CONFIG_CONTROL_DESIGN'"));
    fs->schema_identifiers_(schema_tmp);
    header_instances->Append((SDAI_Application_instance *)fs, completeSE);

    sc->registry = registry;
    sc->instance_list = &instance_list;

    sc->default_context = Add_Default_Geometric_Context(sc);

    sc->application_context = (SdaiApplication_context *)sc->registry->ObjCreate("APPLICATION_CONTEXT");
    sc->instance_list->Append((STEPentity *)sc->application_context, completeSE);
    sc->application_context->application_("'CONFIGURATION CONTROLLED 3D DESIGNS OF MECHANICAL PARTS AND ASSEMBLIES'");

    sc->design_context = (SdaiDesign_context *)sc->registry->ObjCreate("DESIGN_CONTEXT");
    sc->instance_list->Append((STEPentity *)sc->design_context, completeSE);
    sc->design_context->name_("''");
    sc->design_context->life_cycle_stage_("'design'");
    sc->design_context->frame_of_reference_(sc->application_context);

    sc->solid_to_step = new std::map<struct directory *, STEPentity *>;
    sc->solid_to_step_shape = new std::map<struct directory *, STEPentity *>;
    sc->solid_to_step_manifold = new std::map<struct directory *, STEPentity *>;
    sc->comb_to_step = new std::map<struct directory *, STEPentity *>;
    sc->comb_to_step_shape = new std::map<struct directory *, STEPentity *>;
    sc->comb_to_step_manifold = new std::map<struct directory *, STEPentity *>;

    for (int i = 0; i < path_cnt; i++) {
        /* Now, add actual DATA */
        struct directory *dp = paths[i];
        struct rt_db_internal intern;
        rt_db_get_internal(&intern, dp, dbip, bn_mat_identity, &rt_uniresource);
        RT_CK_DB_INTERNAL(&intern);
        Object_To_STEP(dp, &intern, wdbp, sc);
        rt_db_free_internal(&intern);
    }

    /* Write STEP file */
    if (!bu_file_exists(output_file, NULL)) {
        std::ofstream stepout(output_file);
        sfile->WriteExchangeFile(stepout);
    }

    /* Free memory */
    header_instances->DeleteInstances();
    instance_list.DeleteInstances();
    delete dotg;
    delete registry;
    delete sfile;
    delete sc->solid_to_step;
    delete sc->solid_to_step_shape;
    delete sc->solid_to_step_manifold;
    delete sc->comb_to_step;
    delete sc->comb_to_step_shape;
    delete sc->comb_to_step_manifold;
    delete sc;
    bu_vls_free(&scratch_string);
    bu_free(paths, "free dp list");

    return ret;
}
Exemplo n.º 11
0
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;
}
Exemplo n.º 12
0
static int
make_shape(struct rt_wdb *fd, int verbose, int debug, size_t idx, size_t num, point2d_t *v)
{
    size_t i;

    point_t V = VINIT_ZERO;
    vect_t h = VINIT_ZERO;
    struct bu_vls str_sketch = BU_VLS_INIT_ZERO;
    struct bu_vls str_extrude = BU_VLS_INIT_ZERO;

    struct rt_sketch_internal skt;
    struct line_seg *lsg = NULL;

    /* nothing to do? */
    if (num == 0 || !v)
	return 0;

    if (!fd) {
	if (debug)
	    bu_log("ERROR: unable to write out shape\n");
	return 1;
    }

    if (verbose || debug)
	bu_log("%zu vertices\n", num);

    skt.magic = RT_SKETCH_INTERNAL_MAGIC;

    VMOVE(skt.V, V);
    VSET(skt.u_vec, 1.0, 0.0, 0.0);
    VSET(skt.v_vec, 0.0, 1.0, 0.0);

    skt.vert_count = num;
    skt.verts = v;

    /* Specify number of segments */
    skt.curve.count = num;
    /* FIXME: investigate allocation */
    skt.curve.reverse = (int *)bu_calloc(skt.curve.count, sizeof(int), "sketch: reverse");
    skt.curve.segment = (void **)bu_calloc(skt.curve.count, sizeof(void *), "segs");

    /* Insert all line segments except the last one */
    for (i = 0; i < num-1; i++) {
	BU_ALLOC(lsg, struct line_seg);
	lsg->magic = CURVE_LSEG_MAGIC;
	lsg->start = i;
	lsg->end = i + 1;
	skt.curve.segment[i] = (void *)lsg;
    }

    /* Connect the last connected vertex to the first vertex */
    BU_ALLOC(lsg, struct line_seg);
    lsg->magic = CURVE_LSEG_MAGIC;
    lsg->start = num - 1;
    lsg->end = 0;
    skt.curve.segment[num - 1] = (void *)lsg;

    /* write out sketch shape */
    bu_vls_sprintf(&str_sketch, "shape-%zu.sketch", idx);
    mk_sketch(fd, bu_vls_addr(&str_sketch), &skt);

    /* extrude the shape */
    bu_vls_sprintf(&str_extrude, "shape-%zu.extrude", idx);
    VSET(h, 0.0, 0.0, 10.0); /* FIXME: arbitrary height */
    mk_extrusion(fd, bu_vls_addr(&str_extrude), bu_vls_addr(&str_sketch), skt.V, h, skt.u_vec, skt.v_vec, 0);

    /* clean up  */
    bu_vls_free(&str_sketch);
    bu_vls_free(&str_extrude);
    rt_curve_free(&skt.curve);

    return 0;
}
Exemplo n.º 13
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;
}
Exemplo n.º 14
0
int
ged_bot_fuse(struct ged *gedp, int argc, const char **argv)
{
    struct directory *old_dp, *new_dp;
    struct rt_db_internal intern, intern2;
    struct rt_bot_internal *bot;
    int count=0;
    static const char *usage = "new_bot old_bot";

    struct model *m;
    struct nmgregion *r;
    int ret, c, i;
    struct bn_tol *tol = &gedp->ged_wdbp->wdb_tol;
    int total = 0;
    volatile int out_type = 0; /* open edge output type: 0 = none, 1 = show, 2 = plot */
    size_t open_cnt;
    struct bu_vls name_prefix = BU_VLS_INIT_ZERO;

    /* bu_getopt() options */
    static const char *bot_fuse_options = "sp";
    static const char *bot_fuse_options_str = "[-s|-p]";

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

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

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

    /* Turn off getopt's error messages */
    bu_opterr = 0;
    bu_optind = 1;

    /* get all the option flags from the command line */
    while ((c=bu_getopt(argc, (char **)argv, bot_fuse_options)) != -1) {
	switch (c) {
	    case 's':
		{
		    out_type = 1; /* show open edges */
		    break;
		}
	    case 'p':
		{
		    out_type = 2; /* plot open edges */
		    break;
		}
	    default :
		{
		    bu_vls_printf(gedp->ged_result_str, "Unknown option: '%c'", c);
		    return GED_HELP;
		}
	}
    }

    i = argc - 2;

    bu_log("%s: start\n", argv[0]);

    GED_DB_LOOKUP(gedp, old_dp, argv[i+1], LOOKUP_NOISY, GED_ERROR & GED_QUIET);
    GED_DB_GET_INTERNAL(gedp, &intern, old_dp, bn_mat_identity, &rt_uniresource, GED_ERROR);

    if (intern.idb_major_type != DB5_MAJORTYPE_BRLCAD || intern.idb_minor_type != DB5_MINORTYPE_BRLCAD_BOT) {
	bu_vls_printf(gedp->ged_result_str, "%s: %s is not a BOT solid!\n", argv[0], argv[i+1]);
	return GED_ERROR;
    }

    /* create nmg model structure */
    m = nmg_mm();

    /* place bot in nmg structure */
    bu_log("%s: running rt_bot_tess\n", argv[0]);
    ret = rt_bot_tess(&r, m, &intern, &gedp->ged_wdbp->wdb_ttol, tol);

    /* free internal representation of original bot */
    rt_db_free_internal(&intern);

    if (ret != 0) {
	bu_vls_printf(gedp->ged_result_str, "%s: %s fuse failed (1).\n", argv[0], argv[i+1]);
	nmg_km(m);
	return GED_ERROR;
    }

    total = 0;

    /* Step 1 -- the vertices. */
    bu_log("%s: running nmg_vertex_fuse\n", argv[0]);
    count = nmg_vertex_fuse(&m->magic, tol);
    total += count;
    bu_log("%s: %s, %d vertex fused\n", argv[0], argv[i+1], count);

    /* Step 1.5 -- break edges on vertices, before fusing edges */
    bu_log("%s: running nmg_break_e_on_v\n", argv[0]);
    count = nmg_break_e_on_v(&m->magic, tol);
    total += count;
    bu_log("%s: %s, %d broke 'e' on 'v'\n", argv[0], argv[i+1], count);

    if (total) {
	struct nmgregion *r2;
	struct shell *s;

	bu_log("%s: running nmg_make_faces_within_tol\n", argv[0]);

	/* vertices and/or edges have been moved,
	 * may have created out-of-tolerance faces
	 */

	for (BU_LIST_FOR(r2, nmgregion, &m->r_hd)) {
	    for (BU_LIST_FOR(s, shell, &r2->s_hd))
		nmg_make_faces_within_tol(s, tol);
	}
    }

    /* Step 2 -- the face geometry */
    bu_log("%s: running nmg_model_face_fuse\n", argv[0]);
    count = nmg_model_face_fuse(m, tol);
    total += count;
    bu_log("%s: %s, %d faces fused\n", argv[0], argv[i+1], count);

    /* Step 3 -- edges */
    bu_log("%s: running nmg_edge_fuse\n", argv[0]);
    count = nmg_edge_fuse(&m->magic, tol);
    total += count;

    bu_log("%s: %s, %d edges fused\n", argv[0], argv[i+1], count);

    bu_log("%s: %s, %d total fused\n", argv[0], argv[i+1], total);

    if (!BU_SETJUMP) {
	/* try */

	/* convert the nmg model back into a bot */
	bot = nmg_bot(BU_LIST_FIRST(shell, &r->s_hd), tol);

	bu_vls_sprintf(&name_prefix, "open_edges.%s", argv[i]);
	bu_log("%s: running show_dangling_edges\n", argv[0]);
	open_cnt = show_dangling_edges(gedp, &m->magic, bu_vls_addr(&name_prefix), out_type);
	bu_log("%s: WARNING %ld open edges, new BOT may be invalid!!!\n", argv[0], open_cnt);
	bu_vls_free(&name_prefix);

	/* free the nmg model structure */
	nmg_km(m);
    } else {
	/* catch */
	BU_UNSETJUMP;
	bu_vls_printf(gedp->ged_result_str, "%s: %s fuse failed (2).\n", argv[0], argv[i+1]);
	return GED_ERROR;
    } BU_UNSETJUMP;

    RT_DB_INTERNAL_INIT(&intern2);
    intern2.idb_major_type = DB5_MAJORTYPE_BRLCAD;
    intern2.idb_type = ID_BOT;
    intern2.idb_meth = &OBJ[ID_BOT];
    intern2.idb_ptr = (void *)bot;

    GED_DB_DIRADD(gedp, new_dp, argv[i], RT_DIR_PHONY_ADDR, 0, RT_DIR_SOLID, (void *)&intern2.idb_type, GED_ERROR);
    GED_DB_PUT_INTERNAL(gedp, new_dp, &intern2, &rt_uniresource, GED_ERROR);

    bu_log("%s: Created new BOT (%s)\n", argv[0], argv[i]);
    bu_log("%s: Done.\n", argv[0]);

    return GED_OK;
}
int
main(int argc, char *argv[])
{
    struct db_i *dbip;
    struct directory *dp;
    struct rt_db_internal intern;
    struct rt_bot_internal *bot_ip = NULL;
    struct rt_wdb *wdbp;
    struct bu_vls name;
    struct bu_vls bname;
    struct Mesh_Info *prev_mesh = NULL;
    struct Mesh_Info *mesh = NULL;

    bu_vls_init(&name);

    if (argc != 3) {
	bu_exit(1, "Usage: %s file.g object", argv[0]);
    }

    dbip = db_open(argv[1], DB_OPEN_READWRITE);
    if (dbip == DBI_NULL) {
	bu_exit(1, "ERROR: Unable to read from geometry database file %s\n", argv[1]);
    }

    if (db_dirbuild(dbip) < 0)
	bu_exit(1, "ERROR: Unable to read from %s\n", argv[1]);

    dp = db_lookup(dbip, argv[2], LOOKUP_QUIET);
    if (dp == RT_DIR_NULL) {
	bu_exit(1, "ERROR: Unable to look up object %s\n", argv[2]);
    }

    RT_DB_INTERNAL_INIT(&intern)
	if (rt_db_get_internal(&intern, dp, dbip, NULL, &rt_uniresource) < 0) {
	    bu_exit(1, "ERROR: Unable to get internal representation of %s\n", argv[2]);
	}

    if (intern.idb_minor_type != DB5_MINORTYPE_BRLCAD_BOT) {
	bu_exit(1, "ERROR: object %s does not appear to be of type BoT\n", argv[2]);
    } else {
	bot_ip = (struct rt_bot_internal *)intern.idb_ptr;
    }
    RT_BOT_CK_MAGIC(bot_ip);

    for (size_t i_cnt = 1; i_cnt < 3; i_cnt++) {
	mesh = iterate(bot_ip, prev_mesh);
	prev_mesh = mesh;

	// Plot results
	struct bu_vls fname;
	bu_vls_init(&fname);
	bu_vls_printf(&fname, "root3_%d.pl", i_cnt);
	FILE* plot_file = fopen(bu_vls_addr(&fname), "w");
	std::map<size_t, std::vector<size_t> >::iterator f_it;
	std::vector<size_t>::iterator l_it;
	int r = int(256*drand48() + 1.0);
	int g = int(256*drand48() + 1.0);
	int b = int(256*drand48() + 1.0);
	for (f_it = mesh->face_pts.begin(); f_it != mesh->face_pts.end(); f_it++) {
	    l_it = (*f_it).second.begin();
	    plot_face(&mesh->points_p0[(int)(*l_it)], &mesh->points_p0[(int)(*(l_it+1))], &mesh->points_p0[(int)(*(l_it+2))], r, g , b, plot_file);
	}
	fclose(plot_file);
    }

    // When constructing the final BoT, use the limit points for all
    // vertices
    ON_3dPointArray points_inf;
    for (size_t v = 0; v < (size_t)mesh->points_p0.Count(); v++) {
        points_inf.Append(*mesh->points_p0.At((int)v));
	//point_inf(v, mesh, &points_inf);
    }
    // The subdivision process shrinks the bot relative to its original
    // vertex positions - to better approximate the original surface,
    // average the change in position of the original vertices to get a
    // scaling factor and apply it to all points in the final mesh.
    fastf_t scale = 0.0;
    for (size_t pcnt = 0; pcnt < bot_ip->num_vertices; pcnt++) {
	ON_3dVector v1(ON_3dPoint(&bot_ip->vertices[pcnt*3]));
	ON_3dVector v2(*points_inf.At((int)pcnt));
	scale += 1 + (v1.Length() - v2.Length())/v1.Length();
    }
    scale = scale / bot_ip->num_vertices;
    for (size_t pcnt = 0; pcnt < (size_t)points_inf.Count(); pcnt++) {
	ON_3dPoint p0(*points_inf.At((int)pcnt));
	ON_3dPoint p1 = p0 * scale;
	*points_inf.At((int)pcnt) = p1;
    }

    wdbp = wdb_dbopen(dbip, RT_WDB_TYPE_DB_DISK);

    fastf_t *vertices = (fastf_t *)bu_malloc(sizeof(fastf_t) * points_inf.Count() * 3, "new verts");
    int *faces = (int *)bu_malloc(sizeof(int) * mesh->face_pts.size() * 3, "new faces");
    for (size_t v = 0; v < (size_t)points_inf.Count(); v++) {
	vertices[v*3] = points_inf[(int)v].x;
	vertices[v*3+1] = points_inf[(int)v].y;
	vertices[v*3+2] = points_inf[(int)v].z;
    }
    std::map<size_t, std::vector<size_t> >::iterator f_it;
    std::vector<size_t>::iterator l_it;
    for (f_it = mesh->face_pts.begin(); f_it != mesh->face_pts.end(); f_it++) {
	l_it = (*f_it).second.begin();
	faces[(*f_it).first*3] = (*l_it);
	faces[(*f_it).first*3+1] = (*(l_it + 1));
	faces[(*f_it).first*3+2] = (*(l_it + 2));
    }

    bu_vls_init(&bname);
    bu_vls_sprintf(&bname, "%s_subd", argv[2]);
    mk_bot(wdbp, bu_vls_addr(&bname), RT_BOT_SOLID, RT_BOT_UNORIENTED, 0, points_inf.Count(), mesh->face_pts.size(), vertices, faces, (fastf_t *)NULL, (struct bu_bitv *)NULL);
    wdb_close(wdbp);
    bu_vls_free(&bname);

    bu_free(vertices, "free subdivision BoT vertices");
    bu_free(faces, "free subdivision BoT faces");

    return 0;
}
Exemplo n.º 16
0
int
parse_model_string(struct bu_vls *format, struct bu_vls *log, const char *opt, const char *input)
{
    int type_int = 0;
    mime_model_t type = MIME_MODEL_UNKNOWN;

    struct bu_vls format_cpy = BU_VLS_INIT_ZERO;
    struct bu_vls path = BU_VLS_INIT_ZERO;

    if (UNLIKELY(!input) || UNLIKELY(strlen(input) == 0)) return MIME_MODEL_UNKNOWN;

    /* If an external routine has specified a format string, that string will
     * override the file extension (but not an explicit option or format prefix.
     * Stash any local format string here for later processing.  The idea is
     * to allow some other routine (say, an introspection of a file looking for
     * some signature string) to override a file extension based type identification.
     * Such introspection is beyond the scope of this function, but should override
     * the file extension mechanism. */
    if (format) bu_vls_sprintf(&format_cpy, "%s", bu_vls_addr(format));

    /* If we have an explicit option, that overrides any other format specifiers */
    if (opt) {
	type_int = bu_file_mime(opt, MIME_MODEL);
	type = (type_int < 0) ? MIME_MODEL_UNKNOWN : (mime_model_t)type_int;
	if (type == MIME_MODEL_UNKNOWN) {
	    /* Have prefix, but doesn't result in a known format - that's an error */
	    if (log) bu_vls_printf(log, "Error: unknown model format \"%s\" specified as an option.\n", opt);
	    bu_vls_free(&format_cpy);
	    return -1;
	}
    }

    /* Try for a format prefix */
    if (extract_format_prefix(format, input)) {
	/* If we don't already have a valid type and we had a format prefix,
	 * find out if it maps to a valid type */
	if (type == MIME_MODEL_UNKNOWN && format) {
	    /* Yes - see if the prefix specifies a model format */
	    type_int = bu_file_mime(bu_vls_addr(format), MIME_MODEL);
	    type = (type_int < 0) ? MIME_MODEL_UNKNOWN : (mime_model_t)type_int;
	    if (type == MIME_MODEL_UNKNOWN) {
		/* Have prefix, but doesn't result in a known format - that's an error */
		if (log) bu_vls_printf(log, "Error: unknown model format \"%s\" specified as a format prefix.\n", bu_vls_addr(format));
		bu_vls_free(&format_cpy);
		return -1;
	    }
	}
    }

    /* If we don't already have a type and we were passed a format string, give it a try */
    if (type == MIME_MODEL_UNKNOWN && format && bu_vls_strlen(&format_cpy) > 0) {
	bu_vls_sprintf(format, "%s", bu_vls_addr(&format_cpy));
	type_int = bu_file_mime(bu_vls_addr(&format_cpy), MIME_MODEL);
	type = (type_int < 0) ? MIME_MODEL_UNKNOWN : (mime_model_t)type_int;
	if (type == MIME_MODEL_UNKNOWN) {
	    /* Have prefix, but doesn't result in a known format - that's an error */
	    if (log) bu_vls_printf(log, "Error: unknown model format \"%s\" passed to parse_model_string.\n", bu_vls_addr(format));
	    bu_vls_free(&format_cpy);
	    return -1;
	}
    }

    /* If we have no prefix or the prefix didn't map to a model type, try file extension */
    if (type == MIME_MODEL_UNKNOWN && extract_path(&path, input)) {
	if (bu_path_component(format, bu_vls_addr(&path), PATH_EXTENSION)) {
	    type_int = bu_file_mime(bu_vls_addr(format), MIME_MODEL);
	    type = (type_int < 0) ? MIME_MODEL_UNKNOWN : (mime_model_t)type_int;
	    if (type == MIME_MODEL_UNKNOWN) {
		/* Have file extension, but doesn't result in a known format - that's an error */
		if (log) bu_vls_printf(log, "Error: file extension \"%s\" does not map to a known model format.\n", bu_vls_addr(format));
		bu_vls_free(&format_cpy);
		bu_vls_free(&path);
		return -1;
	    }
	}
    }
    bu_vls_free(&path);
    bu_vls_free(&format_cpy);
    return (int)type;
}
void
subbrep_planar_init(struct subbrep_object_data *data)
{
    if (!data) return;
    if (data->planar_obj) return;
    BU_GET(data->planar_obj, struct subbrep_object_data);
    subbrep_object_init(data->planar_obj, data->brep);
    bu_vls_sprintf(data->planar_obj->key, "%s", bu_vls_addr(data->key));
    data->planar_obj->obj_cnt = data->obj_cnt;
    (*data->obj_cnt)++;
    bu_vls_sprintf(data->planar_obj->name_root, "%s_%d", bu_vls_addr(data->name_root), *(data->obj_cnt));
    data->planar_obj->type = PLANAR_VOLUME;

    data->planar_obj->local_brep = ON_Brep::New();
    std::map<int, int> face_map;
    std::map<int, int> surface_map;
    std::map<int, int> edge_map;
    std::map<int, int> vertex_map;
    std::map<int, int> loop_map;
    std::map<int, int> c3_map;
    std::map<int, int> c2_map;
    std::map<int, int> trim_map;
    std::set<int> faces;
    std::set<int> fil;
    std::set<int> loops;
    std::set<int> skip_verts;
    std::set<int> skip_edges;
    std::set<int> keep_verts;
    std::set<int> partial_edges;
    std::set<int> isolated_trims;  // collect 2D trims whose parent loops aren't fully included here
    array_to_set(&faces, data->faces, data->faces_cnt);
    array_to_set(&fil, data->fil, data->fil_cnt);
    array_to_set(&loops, data->loops, data->loops_cnt);
    std::map<int, std::set<int> > face_loops;
    std::map<int, std::set<int> >::iterator fl_it;
    std::set<int>::iterator l_it;

    for (int i = 0; i < data->edges_cnt; i++) {
	int c3i;
	int new_edge_curve = 0;
	const ON_BrepEdge *old_edge = &(data->brep->m_E[data->edges[i]]);
	//std::cout << "old edge: " << old_edge->Vertex(0)->m_vertex_index << "," << old_edge->Vertex(1)->m_vertex_index << "\n";

	// See if the vertices from this edge play a role in the planar volume
	int use_edge = 2;
	for (int vi = 0; vi < 2; vi++) {
	    int vert_test = -1;
	    int vert_ind = old_edge->Vertex(vi)->m_vertex_index;
	    if (skip_verts.find(vert_ind) != skip_verts.end()) {
		vert_test = 1;
	    }
	    if (vert_test == -1 && keep_verts.find(vert_ind) != keep_verts.end()) {
		vert_test = 0;
	    }
	    if (vert_test == -1) {
		vert_test = characterize_vert(data, old_edge->Vertex(vi));
		if (vert_test) {
		    skip_verts.insert(vert_ind);
		    ON_3dPoint vp = old_edge->Vertex(vi)->Point();
		    bu_log("vert %d (%f %f %f): %d\n", vert_ind, vp.x, vp.y, vp.z, vert_test);
		} else {
		    keep_verts.insert(vert_ind);
		}
	    }
	    if (vert_test == 1) {
		use_edge--;
	    }
	}

	if (use_edge == 0) {
	    bu_log("skipping edge %d - both verts are skips\n", old_edge->m_edge_index);
	    skip_edges.insert(old_edge->m_edge_index);
	    continue;
	}

	if (use_edge == 1) {
	    bu_log("One of the verts for edge %d is a skip.\n", old_edge->m_edge_index);
	    partial_edges.insert(old_edge->m_edge_index);
	    continue;
	}

	// Get the 3D curves from the edges
	if (c3_map.find(old_edge->EdgeCurveIndexOf()) == c3_map.end()) {
	    ON_Curve *nc = old_edge->EdgeCurveOf()->Duplicate();
	    ON_Curve *tc = old_edge->EdgeCurveOf()->Duplicate();
	    if (tc->IsLinear()) {
		c3i = data->planar_obj->local_brep->AddEdgeCurve(nc);
		c3_map[old_edge->EdgeCurveIndexOf()] = c3i;
	    } else {
		ON_Curve *c3 = new ON_LineCurve(old_edge->Vertex(0)->Point(), old_edge->Vertex(1)->Point());
		c3i = data->planar_obj->local_brep->AddEdgeCurve(c3);
		c3_map[old_edge->EdgeCurveIndexOf()] = c3i;
		new_edge_curve = 1;
	    }
	} else {
	    c3i = c3_map[old_edge->EdgeCurveIndexOf()];
	}


	// Get the vertices from the edges
	int v[2];
	for (int vi = 0; vi < 2; vi++) {
	    if (vertex_map.find(old_edge->Vertex(vi)->m_vertex_index) == vertex_map.end()) {
		ON_BrepVertex& newvvi = data->planar_obj->local_brep->NewVertex(old_edge->Vertex(vi)->Point(), old_edge->Vertex(vi)->m_tolerance);
		v[vi] = newvvi.m_vertex_index;
		vertex_map[old_edge->Vertex(vi)->m_vertex_index] = v[vi];
	    } else {
		v[vi] = vertex_map[old_edge->Vertex(vi)->m_vertex_index];
	    }
	}

	ON_BrepEdge& new_edge = data->planar_obj->local_brep->NewEdge(data->planar_obj->local_brep->m_V[v[0]], data->planar_obj->local_brep->m_V[v[1]], c3i, NULL ,0);
	edge_map[old_edge->m_edge_index] = new_edge.m_edge_index;

	// Get the 2D curves from the trims
	for (int j = 0; j < old_edge->TrimCount(); j++) {
	    ON_BrepTrim *old_trim = old_edge->Trim(j);
	    if (faces.find(old_trim->Face()->m_face_index) != faces.end()) {
		if (c2_map.find(old_trim->TrimCurveIndexOf()) == c2_map.end()) {
		    ON_Curve *nc = old_trim->TrimCurveOf()->Duplicate();
		    int c2i = data->planar_obj->local_brep->AddTrimCurve(nc);
		    c2_map[old_trim->TrimCurveIndexOf()] = c2i;
		    //std::cout << "c2i: " << c2i << "\n";
		}
	    }
	}

	// Get the faces and surfaces from the trims
	for (int j = 0; j < old_edge->TrimCount(); j++) {
	    ON_BrepTrim *old_trim = old_edge->Trim(j);
	    if (face_map.find(old_trim->Face()->m_face_index) == face_map.end()) {
		if (faces.find(old_trim->Face()->m_face_index) != faces.end()) {
		    ON_Surface *ns = old_trim->Face()->SurfaceOf()->Duplicate();
		    ON_Surface *ts = old_trim->Face()->SurfaceOf()->Duplicate();
		    if (ts->IsPlanar(NULL, BREP_PLANAR_TOL)) {
			int nsid = data->planar_obj->local_brep->AddSurface(ns);
			surface_map[old_trim->Face()->SurfaceIndexOf()] = nsid;
			ON_BrepFace &new_face = data->planar_obj->local_brep->NewFace(nsid);
			face_map[old_trim->Face()->m_face_index] = new_face.m_face_index;
			//std::cout << "old face " << old_trim->Face()->m_face_index << " is now " << new_face.m_face_index << "\n";
			if (fil.find(old_trim->Face()->m_face_index) != fil.end()) {
			    data->planar_obj->local_brep->FlipFace(new_face);
			}
		    }
		}
	    }
	}

	// Get the loops from the trims
	for (int j = 0; j < old_edge->TrimCount(); j++) {
	    ON_BrepTrim *old_trim = old_edge->Trim(j);
	    ON_BrepLoop *old_loop = old_trim->Loop();
	    if (face_map.find(old_trim->Face()->m_face_index) != face_map.end()) {
		if (loops.find(old_loop->m_loop_index) != loops.end()) {
		    if (loop_map.find(old_loop->m_loop_index) == loop_map.end()) {
			face_loops[old_trim->Face()->m_face_index].insert(old_loop->m_loop_index);
		    }
		}
	    }
	}
    }
    for (fl_it = face_loops.begin(); fl_it != face_loops.end(); fl_it++) {
	int loop_cnt = fl_it->second.size();
	if (loop_cnt == 1) {
	    // If we have only one loop on a face it's an outer loop,
	    // whatever it was in the original brep.
	    const ON_BrepLoop *old_loop = &(data->brep->m_L[*(fl_it->second.begin())]);
	    ON_BrepLoop &nl = data->planar_obj->local_brep->NewLoop(ON_BrepLoop::outer, data->planar_obj->local_brep->m_F[face_map[fl_it->first]]);
	    loop_map[old_loop->m_loop_index] = nl.m_loop_index;
	} else {
	    bu_log("loop_cnt: %d\n", loop_cnt);
	    // If we ended up with multiple loops, one of them should be an outer loop
	    // and the rest inner loops
	    // Get the outer loop first
	    for (l_it = fl_it->second.begin(); l_it != fl_it->second.end(); l_it++) {
		const ON_BrepLoop *old_loop = &(data->brep->m_L[*l_it]);
		if (data->brep->LoopDirection(data->brep->m_L[*l_it]) == 1) {
		    ON_BrepLoop &nl = data->planar_obj->local_brep->NewLoop(ON_BrepLoop::outer, data->planar_obj->local_brep->m_F[face_map[fl_it->first]]);
		    loop_map[old_loop->m_loop_index] = nl.m_loop_index;
		}
	    }
	    // Now get the inner loops;
	    for (l_it = fl_it->second.begin(); l_it != fl_it->second.end(); l_it++) {
		const ON_BrepLoop *old_loop = &(data->brep->m_L[*l_it]);
		if (data->brep->LoopDirection(data->brep->m_L[*l_it]) != 1) {
		    ON_BrepLoop &nl = data->planar_obj->local_brep->NewLoop(ON_BrepLoop::inner, data->planar_obj->local_brep->m_F[face_map[fl_it->first]]);
		    loop_map[old_loop->m_loop_index] = nl.m_loop_index;
		}
	    }
	}
    }

    // Now, create new trims using the old loop definitions and the maps
    std::map<int, int>::iterator loop_it;
    std::set<int> evaluated;
    for (loop_it = loop_map.begin(); loop_it != loop_map.end(); loop_it++) {
	const ON_BrepLoop *old_loop = &(data->brep->m_L[(*loop_it).first]);
	ON_BrepLoop &new_loop = data->planar_obj->local_brep->m_L[(*loop_it).second];
	for (int j = 0; j < old_loop->TrimCount(); j++) {
	    const ON_BrepTrim *old_trim = old_loop->Trim(j);
	    ON_BrepEdge *o_edge = old_trim->Edge();
	    if (!o_edge) {
		/* If we didn't have an edge originally, we need to add the 2d curve here */
		if (c2_map.find(old_trim->TrimCurveIndexOf()) == c2_map.end()) {
		    ON_Curve *nc = old_trim->TrimCurveOf()->Duplicate();
		    int c2i = data->planar_obj->local_brep->AddTrimCurve(nc);
		    c2_map[old_trim->TrimCurveIndexOf()] = c2i;
		}
		if (vertex_map.find(old_trim->Vertex(0)->m_vertex_index) == vertex_map.end()) {
		    ON_BrepVertex& newvs = data->planar_obj->local_brep->NewVertex(old_trim->Vertex(0)->Point(), old_trim->Vertex(0)->m_tolerance);
		    vertex_map[old_trim->Vertex(0)->m_vertex_index] = newvs.m_vertex_index;
		    ON_BrepTrim &nt = data->planar_obj->local_brep->NewSingularTrim(newvs, new_loop, old_trim->m_iso, c2_map[old_trim->TrimCurveIndexOf()]);
		    nt.m_tolerance[0] = old_trim->m_tolerance[0];
		    nt.m_tolerance[1] = old_trim->m_tolerance[1];
		} else {
		    ON_BrepTrim &nt = data->planar_obj->local_brep->NewSingularTrim(data->planar_obj->local_brep->m_V[vertex_map[old_trim->Vertex(0)->m_vertex_index]], new_loop, old_trim->m_iso, c2_map[old_trim->TrimCurveIndexOf()]);
		    nt.m_tolerance[0] = old_trim->m_tolerance[0];
		    nt.m_tolerance[1] = old_trim->m_tolerance[1];
		}
		continue;
	    }

	    if (evaluated.find(o_edge->m_edge_index) != evaluated.end()) {
		bu_log("edge %d already handled, continuing...\n", o_edge->m_edge_index);
		continue;
	    }

	    // Don't use a trim connected to an edge we are skipping
	    if (skip_edges.find(o_edge->m_edge_index) != skip_edges.end()) {
		bu_log("edge %d is skipped, continuing...\n", o_edge->m_edge_index);
		evaluated.insert(o_edge->m_edge_index);
		continue;
	    }

	    int is_partial = 0;
	    if (partial_edges.find(o_edge->m_edge_index) != partial_edges.end()) is_partial = 1;

	    if (!is_partial) {
		ON_BrepEdge &n_edge = data->planar_obj->local_brep->m_E[edge_map[o_edge->m_edge_index]];
		ON_Curve *ec = o_edge->EdgeCurveOf()->Duplicate();
		if (ec->IsLinear()) {
		    ON_BrepTrim &nt = data->planar_obj->local_brep->NewTrim(n_edge, old_trim->m_bRev3d, new_loop, c2_map[old_trim->TrimCurveIndexOf()]);
		    nt.m_tolerance[0] = old_trim->m_tolerance[0];
		    nt.m_tolerance[1] = old_trim->m_tolerance[1];
		    nt.m_iso = old_trim->m_iso;
		} else {
		    // Wasn't linear, but wasn't partial either - replace with a line
		    ON_Curve *c2_orig = old_trim->TrimCurveOf()->Duplicate();
		    ON_3dPoint p1 = c2_orig->PointAt(c2_orig->Domain().Min());
		    ON_3dPoint p2 = c2_orig->PointAt(c2_orig->Domain().Max());
		    ON_Curve *c2 = new ON_LineCurve(p1, p2);
		    c2->ChangeDimension(2);
		    int c2i = data->planar_obj->local_brep->AddTrimCurve(c2);
		    ON_BrepTrim &nt = data->planar_obj->local_brep->NewTrim(n_edge, old_trim->m_bRev3d, new_loop, c2i);
		    nt.m_tolerance[0] = old_trim->m_tolerance[0];
		    nt.m_tolerance[1] = old_trim->m_tolerance[1];
		    nt.m_iso = old_trim->m_iso;
		    delete c2_orig;
		}
		delete ec;
	    } else {
		// Partial edge - let the fun begin
		ON_3dPoint p1, p2;
		ON_BrepEdge *next_edge;
		bu_log("working a partial edge: %d\n", o_edge->m_edge_index);
		int v[2];
		v[0] = o_edge->Vertex(0)->m_vertex_index;
		v[1] = o_edge->Vertex(1)->m_vertex_index;
		// figure out which trim point we can use, the min or max
		int pos1 = 0;
		if (skip_verts.find(v[0]) != skip_verts.end()) {
		    pos1 = 1;
		}
		int j_next = j;
		ON_Curve *c2_orig = old_trim->TrimCurveOf()->Duplicate();
		ON_Curve *c2_next = NULL;
		int walk_dir = 1;
		// bump the loop iterator to get passed any skipped edges to
		// the next partial
		while (!c2_next) {
		    (walk_dir == 1) ? j_next++ : j_next--;
		    if (j_next == old_loop->TrimCount()) {
			j_next = 0;
		    }
		    if (j_next == -1) {
			j_next = old_loop->TrimCount() - 1;
		    }
		    const ON_BrepTrim *next_trim = old_loop->Trim(j_next);
		    next_edge = next_trim->Edge();
		    if (!next_edge) continue;
		    if (skip_edges.find(next_edge->m_edge_index) == skip_edges.end()) {
			if (partial_edges.find(next_edge->m_edge_index) != partial_edges.end()) {
			    bu_log("found next partial edge %d\n", next_edge->m_edge_index);
			    evaluated.insert(next_edge->m_edge_index);
			    c2_next = next_trim->TrimCurveOf()->Duplicate();
			} else {
			    bu_log("partial edge %d followed by non-partial %d, need to go the other way\n", o_edge->m_edge_index, next_edge->m_edge_index);
			    j_next--;
			    walk_dir = -1;
			}
		    } else {
			bu_log("skipping fully ignored edge %d\n", next_edge->m_edge_index);
			evaluated.insert(next_edge->m_edge_index);
		    }
		}
		int v2[2];
		v2[0] = next_edge->Vertex(0)->m_vertex_index;
		v2[1] = next_edge->Vertex(1)->m_vertex_index;
		// figure out which trim point we can use, the min or max
		int pos2 = 0;
		if (skip_verts.find(v2[0]) != skip_verts.end()) {
		    pos2 = 1;
		}

		int vmapped[2];
		if (vertex_map.find(o_edge->Vertex(pos1)->m_vertex_index) == vertex_map.end()) {
		    ON_BrepVertex& newvvi = data->planar_obj->local_brep->NewVertex(o_edge->Vertex(pos1)->Point(), o_edge->Vertex(pos1)->m_tolerance);
		    vertex_map[o_edge->Vertex(pos1)->m_vertex_index] = newvvi.m_vertex_index;
		}
		if (vertex_map.find(next_edge->Vertex(pos2)->m_vertex_index) == vertex_map.end()) {
		    ON_BrepVertex& newvvi = data->planar_obj->local_brep->NewVertex(next_edge->Vertex(pos2)->Point(), next_edge->Vertex(pos2)->m_tolerance);
		    vertex_map[next_edge->Vertex(pos2)->m_vertex_index] = newvvi.m_vertex_index;
		}

		// If walk_dir is -1, need to flip things around (I think...) the verts and trim points
		// will be swapped compared to a forward walk
		if (walk_dir == -1) {
		    vmapped[1] = vertex_map[o_edge->Vertex(pos1)->m_vertex_index];
		    vmapped[0] = vertex_map[next_edge->Vertex(pos2)->m_vertex_index];
		} else {
		    vmapped[0] = vertex_map[o_edge->Vertex(pos1)->m_vertex_index];
		    vmapped[1] = vertex_map[next_edge->Vertex(pos2)->m_vertex_index];
		}

		// New Edge curve
		ON_Curve *c3 = new ON_LineCurve(o_edge->Vertex(pos1)->Point(), next_edge->Vertex(pos2)->Point());
		int c3i = data->planar_obj->local_brep->AddEdgeCurve(c3);
		ON_BrepEdge& new_edge = data->planar_obj->local_brep->NewEdge(data->planar_obj->local_brep->m_V[vmapped[0]], data->planar_obj->local_brep->m_V[vmapped[1]], c3i, NULL ,0);

		// Again, flip if walk_dir is -1
		if (walk_dir == -1) {
		    p2 = c2_orig->PointAt(c2_orig->Domain().Min());
		    p1 = c2_next->PointAt(c2_orig->Domain().Max());
		} else {
		    p1 = c2_orig->PointAt(c2_orig->Domain().Min());
		    p2 = c2_next->PointAt(c2_orig->Domain().Max());
		}
		std::cout << "p1: " << pout(p1) << "\n";
		std::cout << "p2: " << pout(p2) << "\n";
		ON_Curve *c2 = new ON_LineCurve(p1, p2);
		c2->ChangeDimension(2);
		int c2i = data->planar_obj->local_brep->AddTrimCurve(c2);
		ON_BrepTrim &nt = data->planar_obj->local_brep->NewTrim(new_edge, false, new_loop, c2i);
		nt.m_tolerance[0] = old_trim->m_tolerance[0];
		nt.m_tolerance[1] = old_trim->m_tolerance[1];
		nt.m_iso = old_trim->m_iso;
		delete c2_orig;
		delete c2_next;
	    }
	}
    }

    // If there is a possibility of a negative volume for the planar solid, do a test.
    // The only way to get a negative planar solid in this context is if that solid is
    // "inside" a non-planar shape (it would be "part of" the parent shape if it were
    // planar and it would be a separate shape altogether if it were not topologically
    // connected.  So we take one partial edge, find its associated non-planar faces,
    // and collect all the partial and skipped edges from that face and any non-planar
    // faces associated with the other partial/skipped edges.
    //
    // TODO - We still have an unhandled possibility here - the self-intersecting
    // planar_obj.  For example:
    //
    //           *                *
    //       *       *        *       *
    //     *     *      *   *    *      *
    //    *     * *      * *    * *      *
    //   *     *   *           *   *      *
    //   * *  *     * * * * * *     *  *  *
    //
    if (partial_edges.size() > 0) {
	std::queue<int> connected_faces;
	std::set<int> relevant_edges;
	std::set<int>::iterator re_it;
	std::set<int> efaces;
	std::set<int>::iterator f_it;
	std::set<int> found_faces;
	const ON_BrepEdge *seed_edge = &(data->brep->m_E[*partial_edges.begin()]);
	for (int j = 0; j < seed_edge->TrimCount(); j++) {
	    ON_BrepTrim *trim = seed_edge->Trim(j);
	    efaces.insert(trim->Face()->m_face_index);
	}
	for(f_it = efaces.begin(); f_it != efaces.end(); f_it++) {
	    surface_t stype = GetSurfaceType(data->brep->m_F[*f_it].SurfaceOf(), NULL);
	    if (stype != SURFACE_PLANE) {
		connected_faces.push(data->brep->m_F[*f_it].m_face_index);
	    }
	}
	while (!connected_faces.empty()) {
	    int face_index = connected_faces.front();
	    connected_faces.pop();
	    std::set<int> local_edges;
	    std::set<int>::iterator le_it;
	    found_faces.insert(face_index);
	    const ON_BrepFace *face = &(data->brep->m_F[face_index]);
	    const ON_BrepLoop *loop = NULL;
	    // Find the loop in this face that is associated with this subbrep
	    for (int i = 0; i < face->LoopCount(); i++) {
		int loop_ind = face->Loop(i)->m_loop_index;
		if (loops.find(loop_ind) != loops.end()) {
		    loop = &(data->brep->m_L[loop_ind]);
		    break;
		}
	    }
	    // Collect the edges that are partial or skipped
	    for (int i = 0; i < loop->TrimCount(); i++) {
		const ON_BrepTrim *trim = loop->Trim(i);
		ON_BrepEdge *edge = trim->Edge();
		if (edge) {
		    if (partial_edges.find(edge->m_edge_index) != partial_edges.end()) {
			relevant_edges.insert(edge->m_edge_index);
			local_edges.insert(edge->m_edge_index);
		    }
		    if (skip_edges.find(edge->m_edge_index) != skip_edges.end()) {
			relevant_edges.insert(edge->m_edge_index);
			local_edges.insert(edge->m_edge_index);
		    }
		}
	    }
	    // For each collected partial/skipped edge, add any faces not already
	    // found to the queue.
	    for (le_it = local_edges.begin(); le_it != local_edges.end(); le_it++) {
		const ON_BrepEdge *edge = &(data->brep->m_E[*le_it]);
		for (int j = 0; j < edge->TrimCount(); j++) {
		    ON_BrepTrim *trim = edge->Trim(j);
		    if (found_faces.find(trim->Face()->m_face_index) == found_faces.end()) {
			found_faces.insert(trim->Face()->m_face_index);
			connected_faces.push(trim->Face()->m_face_index);
		    }
		}
	    }
	}
	// Build two bounding boxes - one with the new verts in planar_obj, and the other with
	// the edges found above.
	ON_BoundingBox pbb, ebb;
	ON_MinMaxInit(&pbb.m_min, &pbb.m_max);
	ON_MinMaxInit(&ebb.m_min, &ebb.m_max);
	for (int i = 0; i < data->planar_obj->local_brep->m_V.Count(); i++) {
	    const ON_BrepVertex *v = &(data->planar_obj->local_brep->m_V[i]);
	    pbb.Set(v->Point(), true);
	}
	for (re_it = relevant_edges.begin(); re_it != relevant_edges.end(); re_it++) {
	    const ON_BrepEdge *e = &(data->brep->m_E[*re_it]);
	    ON_BoundingBox cbb = e->EdgeCurveOf()->BoundingBox();
	    ebb.Set(cbb.m_min, true);
	    ebb.Set(cbb.m_max, true);
	}
	//std::cout << "in pbb.s rpp " << pout(pbb.m_min) << " " << pout(pbb.m_max) << "\n";
	//std::cout << "in ebb.s rpp " << pout(ebb.m_min) << " " << pout(ebb.m_max) << "\n";

	if (ebb.Includes(pbb)) {
	    bu_log("negative volume\n");
	    data->planar_obj->negative_shape = -1;
	} else {
	    bu_log("positive volume\n");
	    data->planar_obj->negative_shape = 1;
	}
	data->planar_obj->params->bool_op = (data->planar_obj->negative_shape == -1) ? '-' : 'u';
    }

    // Need to preserve the vertex map for this, since we're not done building up the brep
    map_to_array(&(data->planar_obj->planar_obj_vert_map), &(data->planar_obj->planar_obj_vert_cnt), &vertex_map);

    data->planar_obj->local_brep->SetTrimTypeFlags(true);

}