int ged_comb_color(struct rt_wdb *wdbp, int argc, const char *argv[]) { int i; int val; register struct directory *dp; struct rt_db_internal intern; struct rt_comb_internal *comb; static const char *usage = "comb_color combination R G B"; GED_CHECK_DATABASE_OPEN(wdbp, GED_ERROR); GED_CHECK_READ_ONLY(wdbp, GED_ERROR); /* initialize result */ bu_vls_trunc(&wdbp->wdb_result_str, 0); wdbp->wdb_result = GED_RESULT_NULL; wdbp->wdb_result_flags = 0; /* must be wanting help */ if (argc == 1) { wdbp->wdb_result_flags |= GED_RESULT_FLAGS_HELP_BIT; bu_vls_printf(&wdbp->wdb_result_str, "Usage: %s %s", argv[0], usage); return GED_OK; } if (argc != 5) { bu_vls_printf(&wdbp->wdb_result_str, "Usage: %s %s", argv[0], usage); return GED_ERROR; } GED_DB_LOOKUP(wdbp, dp, argv[1], LOOKUP_NOISY, GED_ERROR); GED_CHECK_COMB(wdbp, dp, GED_ERROR); GED_DB_GET_INTERNAL(wdbp, &intern, dp, (fastf_t *)NULL, &rt_uniresource, GED_ERROR); comb = (struct rt_comb_internal *)intern.idb_ptr; RT_CK_COMB(comb); for (i = 0; i < 3; ++i) { if (sscanf(argv[i+2], "%d", &val) != 1 || val < 0 || 255 < val) { bu_vls_printf(&wdbp->wdb_result_str,"RGB value out of range: %s", argv[i + 2]); rt_db_free_internal(&intern, &rt_uniresource); return GED_ERROR; } else comb->rgb[i] = val; } comb->rgb_valid = 1; GED_DB_PUT_INTERNAL(wdbp, dp, &intern, &rt_uniresource, GED_ERROR); return GED_OK; }
int ged_adjust(struct ged *gedp, int argc, const char *argv[]) { int status; struct directory *dp; char *name; struct rt_db_internal intern; static const char *usage = "object attr value ?attr value?"; GED_CHECK_DATABASE_OPEN(gedp, GED_ERROR); GED_CHECK_READ_ONLY(gedp, GED_ERROR); GED_CHECK_ARGC_GT_0(gedp, argc, GED_ERROR); /* initialize result */ bu_vls_trunc(gedp->ged_result_str, 0); /* must be wanting help */ if (argc == 1) { bu_vls_printf(gedp->ged_result_str, "Usage: %s %s", argv[0], usage); return GED_HELP; } if (argc < 4) { bu_vls_printf(gedp->ged_result_str, "Usage: %s %s", argv[0], usage); return GED_ERROR; } name = (char *)argv[1]; GED_DB_LOOKUP(gedp, dp, name, LOOKUP_QUIET, GED_ERROR); GED_DB_GET_INTERNAL(gedp, &intern, dp, (matp_t)NULL, &rt_uniresource, GED_ERROR); RT_CK_DB_INTERNAL(&intern); /* Find out what type of object we are dealing with and tweak it. */ RT_CK_FUNCTAB(intern.idb_meth); if (!intern.idb_meth->ft_adjust) { bu_vls_printf(gedp->ged_result_str, "wdb_export(%s) adjust failure", name); return GED_ERROR; } status = intern.idb_meth->ft_adjust(gedp->ged_result_str, &intern, argc-2, argv+2); if (status == GED_OK && wdb_put_internal(gedp->ged_wdbp, name, &intern, 1.0) < 0) { bu_vls_printf(gedp->ged_result_str, "wdb_export(%s) failure", name); rt_db_free_internal(&intern); return GED_ERROR; } return GED_OK; }
int ged_copy(struct ged *gedp, int argc, const char *argv[]) { struct directory *from_dp; struct bu_external external; static const char *usage = "from to"; GED_CHECK_DATABASE_OPEN(gedp, GED_ERROR); GED_CHECK_READ_ONLY(gedp, GED_ERROR); GED_CHECK_ARGC_GT_0(gedp, argc, GED_ERROR); /* initialize result */ bu_vls_trunc(gedp->ged_result_str, 0); /* must be wanting help */ if (argc == 1) { bu_vls_printf(gedp->ged_result_str, "Usage: %s %s", argv[0], usage); return GED_HELP; } if (argc != 3) { bu_vls_printf(gedp->ged_result_str, "Usage: %s %s", argv[0], usage); return GED_ERROR; } GED_DB_LOOKUP(gedp, from_dp, argv[1], LOOKUP_NOISY, GED_ERROR & GED_QUIET); GED_CHECK_EXISTS(gedp, argv[2], LOOKUP_QUIET, GED_ERROR); if (db_get_external(&external, from_dp, gedp->ged_wdbp->dbip)) { bu_vls_printf(gedp->ged_result_str, "Database read error, aborting\n"); return GED_ERROR; } if (wdb_export_external(gedp->ged_wdbp, &external, argv[2], from_dp->d_flags, from_dp->d_minor_type) < 0) { bu_free_external(&external); bu_vls_printf(gedp->ged_result_str, "Failed to write new object (%s) to database - aborting!!\n", argv[2]); return GED_ERROR; } bu_free_external(&external); return GED_OK; }
int ged_bot_condense(struct ged *gedp, int argc, const char *argv[]) { struct directory *old_dp, *new_dp; struct rt_db_internal intern; struct rt_bot_internal *bot; int count2=0; static const char *usage = "new_bot old_bot"; GED_CHECK_DATABASE_OPEN(gedp, GED_ERROR); GED_CHECK_READ_ONLY(gedp, GED_ERROR); GED_CHECK_ARGC_GT_0(gedp, argc, GED_ERROR); /* initialize result */ bu_vls_trunc(gedp->ged_result_str, 0); /* must be wanting help */ if (argc == 1) { bu_vls_printf(gedp->ged_result_str, "Usage: %s %s", argv[0], usage); return GED_HELP; } if (argc != 3) { bu_vls_printf(gedp->ged_result_str, "Usage: %s %s", argv[0], usage); return GED_ERROR; } GED_DB_LOOKUP(gedp, old_dp, argv[2], 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[2]); return GED_ERROR; } bot = (struct rt_bot_internal *)intern.idb_ptr; RT_BOT_CK_MAGIC(bot); count2 = rt_bot_condense(bot); bu_vls_printf(gedp->ged_result_str, "%s: %d dead vertices eliminated\n", argv[0], count2); GED_DB_DIRADD(gedp, new_dp, argv[1], RT_DIR_PHONY_ADDR, 0, RT_DIR_SOLID, (void *)&intern.idb_type, GED_ERROR); GED_DB_PUT_INTERNAL(gedp, new_dp, &intern, &rt_uniresource, GED_ERROR); return GED_OK; }
int ged_bot(struct ged *gedp, int argc, const char *argv[]) { struct directory *bot_dp; struct rt_db_internal intern; struct rt_bot_internal *bot; const char *cmd = argv[0]; const char *sub = NULL; const char *arg = NULL; const char *primitive = NULL; size_t len; fastf_t tmp; fastf_t propVal; static const char *usage = "get (faces|minEdge|maxEdge|orientation|type|vertices) bot\nchull bot_in bot_out\n"; 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) { bu_vls_printf(gedp->ged_result_str, "Usage: %s %s", cmd, usage); return GED_ERROR; } /* determine subcommand */ sub = argv[1]; len = strlen(sub); if (bu_strncmp(sub, "get", len) == 0) { primitive = argv[argc - 1]; } if (bu_strncmp(sub, "chull", len) == 0) { primitive = argv[2]; } if (primitive == NULL) { bu_vls_printf(gedp->ged_result_str, "%s: %s is not a known subcommand!", cmd, sub); return GED_ERROR; } /* get bot */ GED_DB_LOOKUP(gedp, bot_dp, primitive, LOOKUP_NOISY, GED_ERROR & GED_QUIET); GED_DB_GET_INTERNAL(gedp, &intern, bot_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!", cmd, primitive); return GED_ERROR; } bot = (struct rt_bot_internal *)intern.idb_ptr; RT_BOT_CK_MAGIC(bot); if (bu_strncmp(sub, "get", len) == 0) { arg = argv[2]; propVal = rt_bot_propget(bot, arg); /* print result string */ if (!EQUAL(propVal, -1.0)) { tmp = (int) propVal; /* int result */ if (EQUAL(propVal, tmp)) { bu_vls_printf(gedp->ged_result_str, "%d", (int) propVal); } /* float result */ else { bu_vls_printf(gedp->ged_result_str, "%f", propVal); } } else { bu_vls_printf(gedp->ged_result_str, "%s: %s is not a valid argument!", sub, arg); return GED_ERROR; } } if (bu_strncmp(sub, "chull", len) == 0) { int retval = 0; int fc = 0; int vc = 0; point_t *vert_array; int *faces; unsigned char err = 0; /* must be wanting help */ if (argc < 4) { bu_vls_printf(gedp->ged_result_str, "Usage: %s %s", cmd, usage); return GED_ERROR; } retval = bg_3d_chull(&faces, &fc, &vert_array, &vc, (const point_t *)bot->vertices, (int)bot->num_vertices); if (retval != 3) return GED_ERROR; retval = mk_bot(gedp->ged_wdbp, argv[3], RT_BOT_SOLID, RT_BOT_CCW, err, vc, fc, (fastf_t *)vert_array, faces, NULL, NULL); if (retval) return GED_ERROR; } return GED_OK; }
int ged_copyeval(struct ged *gedp, int argc, const char *argv[]) { static const char *usage = "path_to_old_prim new_prim"; struct _ged_trace_data gtd; struct directory *dp; struct rt_db_internal *ip; struct rt_db_internal internal, new_int; char *tok; int endpos = 0; int i; mat_t start_mat; GED_CHECK_DATABASE_OPEN(gedp, GED_ERROR); GED_CHECK_READ_ONLY(gedp, GED_ERROR); GED_CHECK_ARGC_GT_0(gedp, argc, GED_ERROR); /* initialize result */ bu_vls_trunc(gedp->ged_result_str, 0); /* must be wanting help */ if (argc == 1) { bu_vls_printf(gedp->ged_result_str, "Usage: %s %s", argv[0], usage); return GED_HELP; } if (argc != 3) { bu_vls_printf(gedp->ged_result_str, "Usage: %s %s", argv[0], usage); return GED_ERROR; } /* initialize gtd */ gtd.gtd_gedp = gedp; gtd.gtd_flag = _GED_CPEVAL; gtd.gtd_prflag = 0; /* check if new solid name already exists in description */ GED_CHECK_EXISTS(gedp, argv[2], LOOKUP_QUIET, GED_ERROR); MAT_IDN(start_mat); /* build directory pointer array for desired path */ if (strchr(argv[1], '/')) { tok = strtok((char *)argv[1], "/"); while (tok) { GED_DB_LOOKUP(gedp, gtd.gtd_obj[endpos], tok, LOOKUP_NOISY, GED_ERROR & GED_QUIET); endpos++; tok = strtok((char *)NULL, "/"); } } else { GED_DB_LOOKUP(gedp, gtd.gtd_obj[endpos], argv[1], LOOKUP_NOISY, GED_ERROR & GED_QUIET); endpos++; } if (endpos < 1) { bu_vls_printf(gedp->ged_result_str, "Usage: %s %s", argv[0], usage); return GED_ERROR; } gtd.gtd_objpos = endpos - 1; GED_DB_GET_INTERNAL(gedp, &internal, gtd.gtd_obj[endpos - 1], bn_mat_identity, &rt_uniresource, GED_ERROR); if (endpos > 1) { /* Make sure that final component in path is a solid */ if (internal.idb_type == ID_COMBINATION) { rt_db_free_internal(&internal); bu_vls_printf(gedp->ged_result_str, "final component on path must be a primitive!\n"); return GED_ERROR; } /* Accumulate the matrices */ ged_trace(gtd.gtd_obj[0], 0, start_mat, >d, 1); if (gtd.gtd_prflag == 0) { bu_vls_printf(gedp->ged_result_str, "PATH: "); for (i = 0; i < gtd.gtd_objpos; i++) bu_vls_printf(gedp->ged_result_str, "/%s", gtd.gtd_obj[i]->d_namep); bu_vls_printf(gedp->ged_result_str, " NOT FOUND\n"); rt_db_free_internal(&internal); return GED_ERROR; } /* Have found the desired path - wdb_xform is the transformation matrix */ /* wdb_xform matrix calculated in wdb_trace() */ /* create the new solid */ RT_DB_INTERNAL_INIT(&new_int); if (rt_generic_xform(&new_int, gtd.gtd_xform, &internal, 0, gedp->ged_wdbp->dbip, &rt_uniresource)) { rt_db_free_internal(&internal); bu_vls_printf(gedp->ged_result_str, "ged_copyeval: rt_generic_xform failed\n"); return GED_ERROR; } ip = &new_int; } else ip = &internal; /* should call GED_DB_DIRADD() but need to deal with freeing the * internals on failure. */ dp=db_diradd(gedp->ged_wdbp->dbip, argv[2], RT_DIR_PHONY_ADDR, 0, gtd.gtd_obj[endpos-1]->d_flags, (void *)&ip->idb_type); if (dp == RT_DIR_NULL) { rt_db_free_internal(&internal); if (ip == &new_int) rt_db_free_internal(&new_int); bu_vls_printf(gedp->ged_result_str, "An error has occurred while adding a new object to the database."); return GED_ERROR; } /* should call GED_DB_DIRADD() but need to deal with freeing the * internals on failure. */ if (rt_db_put_internal(dp, gedp->ged_wdbp->dbip, ip, &rt_uniresource) < 0) { /* if (ip == &new_int) then new_int gets freed by the rt_db_put_internal above * regardless of whether it succeeds or not. At this point only internal needs * to be freed. On the other hand if (ip == &internal), the internal gets freed * freed by the rt_db_put_internal above. In this case memory for new_int has * not been allocated. */ if (ip == &new_int) rt_db_free_internal(&internal); bu_vls_printf(gedp->ged_result_str, "Database write error, aborting"); return GED_ERROR; } /* see previous comment */ if (ip == &new_int) rt_db_free_internal(&internal); return GED_OK; }
int ged_dbcopy(struct ged *from_gedp, struct ged *to_gedp, const char *from, const char *to, int fflag) { struct directory *from_dp; struct bu_external external; GED_CHECK_DATABASE_OPEN(from_gedp, GED_ERROR); GED_CHECK_DATABASE_OPEN(to_gedp, GED_ERROR); GED_CHECK_READ_ONLY(to_gedp, GED_ERROR); /* initialize result */ bu_vls_trunc(from_gedp->ged_result_str, 0); bu_vls_trunc(to_gedp->ged_result_str, 0); GED_DB_LOOKUP(from_gedp, from_dp, from, LOOKUP_NOISY, GED_ERROR & GED_QUIET); if (!fflag && db_lookup(to_gedp->ged_wdbp->dbip, to, LOOKUP_QUIET) != RT_DIR_NULL) { bu_vls_printf(from_gedp->ged_result_str, "%s already exists.", to); return GED_ERROR; } if (db_get_external(&external, from_dp, from_gedp->ged_wdbp->dbip)) { bu_vls_printf(from_gedp->ged_result_str, "Database read error, aborting\n"); return GED_ERROR; } if (wdb_export_external(to_gedp->ged_wdbp, &external, to, from_dp->d_flags, from_dp->d_minor_type) < 0) { bu_free_external(&external); bu_vls_printf(from_gedp->ged_result_str, "Failed to write new object (%s) to database - aborting!!\n", to); return GED_ERROR; } bu_free_external(&external); /* Need to do something extra for _GLOBAL */ if (db_version(to_gedp->ged_wdbp->dbip) > 4 && BU_STR_EQUAL(to, DB5_GLOBAL_OBJECT_NAME)) { struct directory *to_dp; struct bu_attribute_value_set avs; const char *val; GED_DB_LOOKUP(to_gedp, to_dp, to, LOOKUP_NOISY, GED_ERROR & GED_QUIET); bu_avs_init_empty(&avs); if (db5_get_attributes(to_gedp->ged_wdbp->dbip, &avs, to_dp)) { bu_vls_printf(from_gedp->ged_result_str, "Cannot get attributes for object %s\n", to_dp->d_namep); return GED_ERROR; } if ((val = bu_avs_get(&avs, "title")) != NULL) to_gedp->ged_wdbp->dbip->dbi_title = strdup(val); if ((val = bu_avs_get(&avs, "units")) != NULL) { double loc2mm; if ((loc2mm = bu_mm_value(val)) > 0) { to_gedp->ged_wdbp->dbip->dbi_local2base = loc2mm; to_gedp->ged_wdbp->dbip->dbi_base2local = 1.0 / loc2mm; } } if ((val = bu_avs_get(&avs, "regionid_colortable")) != NULL) { rt_color_free(); db5_import_color_table((char *)val); } bu_avs_free(&avs); } return GED_OK; }
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 ged_bot_smooth(struct ged *gedp, int argc, const char *argv[]) { char *new_bot_name, *old_bot_name; struct directory *dp_old, *dp_new; struct rt_bot_internal *old_bot; struct rt_db_internal intern; fastf_t tolerance_angle=180.0; int arg_index=1; static const char *usage = "[-t ntol] new_bot old_bot"; GED_CHECK_DATABASE_OPEN(gedp, GED_ERROR); GED_CHECK_READ_ONLY(gedp, GED_ERROR); GED_CHECK_ARGC_GT_0(gedp, argc, GED_ERROR); dp_old = dp_new = RT_DIR_NULL; /* initialize result */ bu_vls_trunc(gedp->ged_result_str, 0); /* must be wanting help */ if (argc == 1) { bu_vls_printf(gedp->ged_result_str, "Usage: %s %s", argv[0], usage); return GED_HELP; } /* check that we are using a version 5 database */ if (db_version(gedp->ged_wdbp->dbip) < 5) { bu_vls_printf(gedp->ged_result_str, "This is an older database version.\nIt does not support BOT surface normals.\nUse \"dbupgrade\" to upgrade this database to the current version.\n"); return GED_ERROR; } if (argc < 3) { bu_vls_printf(gedp->ged_result_str, "Usage: %s %s", argv[0], usage); return GED_ERROR; } while (*argv[arg_index] == '-') { /* this is an option */ if (BU_STR_EQUAL(argv[arg_index], "-t")) { arg_index++; tolerance_angle = atof(argv[arg_index]); } else { bu_vls_printf(gedp->ged_result_str, "Usage: %s %s", argv[0], usage); return GED_ERROR; } arg_index++; } if (arg_index >= argc) { bu_vls_printf(gedp->ged_result_str, "Usage: %s %s", argv[0], usage); return GED_ERROR; } new_bot_name = (char *)argv[arg_index++]; old_bot_name = (char *)argv[arg_index]; GED_DB_LOOKUP(gedp, dp_old, old_bot_name, LOOKUP_QUIET, GED_ERROR); if (!BU_STR_EQUAL(old_bot_name, new_bot_name)) { GED_CHECK_EXISTS(gedp, new_bot_name, LOOKUP_QUIET, GED_ERROR); } else { dp_new = dp_old; } GED_DB_GET_INTERNAL(gedp, &intern, dp_old, NULL, gedp->ged_wdbp->wdb_resp, 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 is not a BOT primitive\n", old_bot_name); rt_db_free_internal(&intern); return GED_ERROR; } old_bot = (struct rt_bot_internal *)intern.idb_ptr; RT_BOT_CK_MAGIC(old_bot); if (rt_bot_smooth(old_bot, old_bot_name, gedp->ged_wdbp->dbip, tolerance_angle*DEG2RAD)) { bu_vls_printf(gedp->ged_result_str, "Failed to smooth %s\n", old_bot_name); rt_db_free_internal(&intern); return GED_ERROR; } if (dp_new == RT_DIR_NULL) { GED_DB_DIRADD(gedp, dp_new, new_bot_name, RT_DIR_PHONY_ADDR, 0, RT_DIR_SOLID, (void *)&intern.idb_type, GED_ERROR); } GED_DB_PUT_INTERNAL(gedp, dp_new, &intern, gedp->ged_wdbp->wdb_resp, GED_ERROR); rt_db_free_internal(&intern); return GED_OK; }
int ged_comb_std(struct ged *gedp, int argc, const char *argv[]) { char *comb_name; int ch; int region_flag = -1; struct directory *dp = RT_DIR_NULL; struct rt_db_internal intern; struct rt_comb_internal *comb = NULL; struct tokens tok_hd; short last_tok; int i; union tree *final_tree; static const char *usage = "[-cr] comb_name <boolean_expr>"; GED_CHECK_DATABASE_OPEN(gedp, GED_ERROR); GED_CHECK_READ_ONLY(gedp, GED_ERROR); GED_CHECK_ARGC_GT_0(gedp, argc, GED_ERROR); /* initialize result */ bu_vls_trunc(gedp->ged_result_str, 0); /* must be wanting help */ if (argc == 1) { bu_vls_printf(gedp->ged_result_str, "Usage: %s %s", argv[0], usage); return GED_HELP; } if (argc < 3) { bu_vls_printf(gedp->ged_result_str, "Usage: %s %s", argv[0], usage); return GED_ERROR; } /* Parse options */ bu_optind = 1; /* re-init bu_getopt() */ while ((ch = bu_getopt(argc, (char * const *)argv, "cgr?")) != -1) { switch (ch) { case 'c': case 'g': region_flag = 0; break; case 'r': region_flag = 1; break; /* XXX How about -p and -v for FASTGEN? */ case '?': default: bu_vls_printf(gedp->ged_result_str, "Usage: %s %s", argv[0], usage); return GED_OK; } } argc -= (bu_optind + 1); argv += bu_optind; comb_name = (char *)*argv++; if (argc == -1) { bu_vls_printf(gedp->ged_result_str, "Usage: %s %s", argv[0], usage); return GED_OK; } if ((region_flag != -1) && (argc == 0)) { /* * Set/Reset the REGION flag of an existing combination */ GED_DB_LOOKUP(gedp, dp, comb_name, LOOKUP_NOISY, GED_ERROR & GED_QUIET); if (!(dp->d_flags & RT_DIR_COMB)) { bu_vls_printf(gedp->ged_result_str, "%s is not a combination\n", comb_name); return GED_ERROR; } GED_DB_GET_INTERNAL(gedp, &intern, dp, (fastf_t *)NULL, &rt_uniresource, GED_ERROR); comb = (struct rt_comb_internal *)intern.idb_ptr; RT_CK_COMB(comb); if (region_flag) { if (!comb->region_flag) { /* assign values from the defaults */ comb->region_id = gedp->ged_wdbp->wdb_item_default++; comb->aircode = gedp->ged_wdbp->wdb_air_default; comb->GIFTmater = gedp->ged_wdbp->wdb_mat_default; comb->los = gedp->ged_wdbp->wdb_los_default; } comb->region_flag = 1; } else comb->region_flag = 0; GED_DB_PUT_INTERNAL(gedp, dp, &intern, &rt_uniresource, GED_ERROR); return GED_OK; } /* * At this point, we know we have a Boolean expression. * If the combination already existed and region_flag is -1, * then leave its region_flag alone. * If the combination didn't exist yet, * then pretend region_flag was 0. * Otherwise, make sure to set its c_flags according to region_flag. */ GED_CHECK_EXISTS(gedp, comb_name, LOOKUP_QUIET, GED_ERROR); dp = RT_DIR_NULL; /* parse Boolean expression */ BU_LIST_INIT(&tok_hd.l); tok_hd.type = TOK_NULL; last_tok = TOK_LPAREN; for (i = 0; i < argc; i++) { char *ptr; ptr = (char *)argv[i]; while (*ptr) { while (*ptr == '(' || *ptr == ')') { switch (*ptr) { case '(': append_lparen(&tok_hd.l); last_tok = TOK_LPAREN; break; case ')': append_rparen(&tok_hd.l); last_tok = TOK_RPAREN; break; } ptr++; } if (*ptr == '\0') continue; if (last_tok == TOK_RPAREN) { /* next token MUST be an operator */ if (add_operator(gedp, &tok_hd.l, *ptr, &last_tok) == GED_ERROR) { free_tokens(&tok_hd.l); return GED_ERROR; } ptr++; } else if (last_tok == TOK_LPAREN) { /* next token MUST be an operand */ int name_len; name_len = add_operand(gedp, &tok_hd.l, ptr); if (name_len < 1) { free_tokens(&tok_hd.l); return GED_ERROR; } last_tok = TOK_TREE; ptr += name_len; } else if (last_tok == TOK_TREE) { /* must be an operator */ if (add_operator(gedp, &tok_hd.l, *ptr, &last_tok) == GED_ERROR) { free_tokens(&tok_hd.l); return GED_ERROR; } ptr++; } else if (last_tok == TOK_UNION || last_tok == TOK_INTER || last_tok == TOK_SUBTR) { /* must be an operand */ int name_len; name_len = add_operand(gedp, &tok_hd.l, ptr); if (name_len < 1) { free_tokens(&tok_hd.l); return GED_ERROR; } last_tok = TOK_TREE; ptr += name_len; } } } if (check_syntax(gedp, &tok_hd.l, comb_name, dp)) { free_tokens(&tok_hd.l); return GED_ERROR; } final_tree = eval_bool(&tok_hd.l); { int flags; flags = RT_DIR_COMB; BU_ALLOC(comb, struct rt_comb_internal); RT_COMB_INTERNAL_INIT(comb); comb->tree = final_tree; comb->region_id = -1; if (region_flag == (-1)) comb->region_flag = 0; else comb->region_flag = region_flag; if (comb->region_flag) { comb->region_flag = 1; comb->region_id = gedp->ged_wdbp->wdb_item_default++; comb->aircode = gedp->ged_wdbp->wdb_air_default; comb->los = gedp->ged_wdbp->wdb_los_default; comb->GIFTmater = gedp->ged_wdbp->wdb_mat_default; bu_vls_printf(gedp->ged_result_str, "Creating region with attrs: region_id=%d, ", comb->region_id); if (comb->aircode) bu_vls_printf(gedp->ged_result_str, "air=%d, ", comb->aircode); bu_vls_printf(gedp->ged_result_str, "los=%d, material_id=%d\n", comb->los, comb->GIFTmater); flags |= RT_DIR_REGION; } RT_DB_INTERNAL_INIT(&intern); intern.idb_major_type = DB5_MAJORTYPE_BRLCAD; intern.idb_type = ID_COMBINATION; intern.idb_meth = &OBJ[ID_COMBINATION]; intern.idb_ptr = (void *)comb; GED_DB_DIRADD(gedp, dp, comb_name, RT_DIR_PHONY_ADDR, 0, flags, (void *)&intern.idb_type, GED_ERROR); GED_DB_PUT_INTERNAL(gedp, dp, &intern, &rt_uniresource, GED_ERROR); } return GED_OK; }