HIDDEN int constraint_set(void *datap, int argc, const char *argv[]) { struct directory *dp; struct bu_attribute_value_set avs = BU_AVS_INIT_ZERO; struct bu_vls expression = BU_VLS_INIT_ZERO; struct ged *gedp = (struct ged *)datap; if (!gedp || argc < 3 || !argv) return BRLCAD_ERROR; GED_CHECK_READ_ONLY(gedp, GED_ERROR); dp = db_lookup(gedp->ged_wdbp->dbip, argv[2], LOOKUP_QUIET); if (!dp) { /* TODO: need to create the object here */ return BRLCAD_ERROR; } if (db5_get_attributes(gedp->ged_wdbp->dbip, &avs, dp)) { bu_vls_printf(gedp->ged_result_str, "Cannot get constraints for %s\n", dp->d_namep); bu_avs_free(&avs); return BRLCAD_ERROR; } bu_vls_from_argv(&expression, argc-4, &argv[4]); (void)bu_avs_add(&avs, argv[3], bu_vls_addr(&expression)); bu_vls_free(&expression); if (db5_update_attributes(dp, &avs, gedp->ged_wdbp->dbip)) { bu_vls_printf(gedp->ged_result_str, "Failed to set constraints on %s\n", dp->d_namep); bu_avs_free(&avs); return GED_ERROR; } bu_avs_free(&avs); return BRLCAD_OK; }
HIDDEN int constraint_eval(void *datap, int argc, const char *argv[]) { size_t i, obj; struct directory *dp; struct bu_attribute_value_set avs; struct bu_attribute_value_pair *avpp; int ret = BRLCAD_OK; struct ged *gedp = (struct ged *)datap; if (!gedp || argc < 1 || !argv) return BRLCAD_ERROR; GED_CHECK_READ_ONLY(gedp, GED_ERROR); /* multiple arguments assumed to be multiple objects */ for (obj = 0; 2+obj < (size_t)argc; obj++) { /* load the constraint object */ dp = db_lookup(gedp->ged_wdbp->dbip, argv[2+obj], LOOKUP_QUIET); if (dp == RT_DIR_NULL) { bu_vls_printf(gedp->ged_result_str, "Unable to find %s in the database.\n", argv[2+obj]); ret = BRLCAD_ERROR; continue; } bu_avs_init_empty(&avs); if (db5_get_attributes(gedp->ged_wdbp->dbip, &avs, dp)) { bu_vls_printf(gedp->ged_result_str, "Cannot get constraints from %s\n", dp->d_namep); ret = BRLCAD_ERROR; } for (i=0, avpp = avs.avp; i < avs.count; i++, avpp++) { bu_vls_printf(gedp->ged_result_str, "Evaluating %s constraint: %s %s\n", argv[2+obj], avpp->name, avpp->value); bu_vls_printf(gedp->ged_result_str, "<<constraint eval here>>\n"); } bu_avs_free(&avs); } return ret; }
void rt_db_free_internal(struct rt_db_internal *ip) { RT_CK_DB_INTERNAL(ip); /* meth is not required since may be asked to free something that * was never set. */ if (ip->idb_meth) { RT_CK_FUNCTAB(ip->idb_meth); if (ip->idb_ptr && ip->idb_meth->ft_ifree) { ip->idb_meth->ft_ifree(ip); } } if (ip->idb_ptr) { ip->idb_ptr = NULL; /* sanity. Should be handled by INIT, below */ } if (ip->idb_avs.magic == BU_AVS_MAGIC) { bu_avs_free(&ip->idb_avs); } RT_DB_INTERNAL_INIT(ip); }
/** * Apply a 4x4 transformation matrix to the internal form of a solid. * * If "free" flag is non-zero, storage for the original solid is * released. If "os" is same as "is", storage for the original solid * is overwritten with the new, transformed solid. * * Returns - * -1 FAIL * 0 OK */ int rt_generic_xform( struct rt_db_internal *op, const mat_t mat, struct rt_db_internal *ip, int release, struct db_i *dbip, struct resource *resp) { struct bu_external ext; int id; struct bu_attribute_value_set avs; RT_CK_DB_INTERNAL(ip); RT_CK_DBI(dbip); RT_CK_RESOURCE(resp); memset(&avs, 0, sizeof(struct bu_attribute_value_set)); id = ip->idb_type; BU_EXTERNAL_INIT(&ext); /* Scale change on export is 1.0 -- no change */ switch (db_version(dbip)) { case 4: if (OBJ[id].ft_export4(&ext, ip, 1.0, dbip, resp) < 0) { bu_log("rt_generic_xform(): %s export failure\n", OBJ[id].ft_name); return -1; /* FAIL */ } if ((release || op == ip)) rt_db_free_internal(ip); RT_DB_INTERNAL_INIT(op); if (OBJ[id].ft_import4(op, &ext, mat, dbip, resp) < 0) { bu_log("rt_generic_xform(): solid import failure\n"); return -1; /* FAIL */ } break; case 5: if (OBJ[id].ft_export5(&ext, ip, 1.0, dbip, resp) < 0) { bu_log("rt_generic_xform(): %s export failure\n", OBJ[id].ft_name); return -1; /* FAIL */ } if ((release || op == ip)) { if (ip->idb_avs.magic == BU_AVS_MAGIC) { /* grab the attributes before they are lost * by rt_db_free_internal or RT_DB_INTERNAL_INIT */ bu_avs_init(&avs, ip->idb_avs.count, "avs"); bu_avs_merge(&avs, &ip->idb_avs); } rt_db_free_internal(ip); } RT_DB_INTERNAL_INIT(op); if (!release && op != ip) { /* just copy the attributes from ip to op */ if (ip->idb_avs.magic == BU_AVS_MAGIC) { bu_avs_init(&op->idb_avs, ip->idb_avs.count, "avs"); bu_avs_merge(&op->idb_avs, &ip->idb_avs); } } else if (avs.magic == BU_AVS_MAGIC) { /* put the saved attributes in the output */ bu_avs_init(&op->idb_avs, avs.count, "avs"); bu_avs_merge(&op->idb_avs, &avs); bu_avs_free(&avs); } if (OBJ[id].ft_import5(op, &ext, mat, dbip, resp) < 0) { bu_log("rt_generic_xform(): solid import failure\n"); return -1; /* FAIL */ } break; } bu_free_external(&ext); RT_CK_DB_INTERNAL(op); return 0; /* 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_draw_guts(struct ged *gedp, int argc, const char *argv[], int kind) { size_t i; int drawtrees_retval; int flag_A_attr=0; int flag_o_nonunique=1; int last_opt=0; struct bu_vls vls = BU_VLS_INIT_ZERO; static const char *usage = "<[-R -C#/#/# -s] objects> | <-o -A attribute name/value pairs>"; /* #define DEBUG_TIMING 1 */ #ifdef DEBUG_TIMING int64_t elapsedtime; #endif 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 == 1) { bu_vls_printf(gedp->ged_result_str, "Usage: %s %s", argv[0], usage); return GED_HELP; } #ifdef DEBUG_TIMING elapsedtime = bu_gettime(); #endif /* skip past cmd */ --argc; ++argv; /* check args for "-A" (attributes) and "-o" */ for (i = 0; i < (size_t)argc; i++) { char *ptr_A=NULL; char *ptr_o=NULL; char *c; if (*argv[i] != '-') { /* Done checking options. If our display is non-empty, * add -R to keep current view. */ if (BU_LIST_NON_EMPTY(gedp->ged_gdp->gd_headDisplay)) { bu_vls_strcat(&vls, " -R"); } break; } ptr_A=strchr(argv[i], 'A'); if (ptr_A) flag_A_attr = 1; ptr_o=strchr(argv[i], 'o'); if (ptr_o) flag_o_nonunique = 2; last_opt = i; if (!ptr_A && !ptr_o) { bu_vls_putc(&vls, ' '); bu_vls_strcat(&vls, argv[i]); continue; } if (strlen(argv[i]) == ((size_t)1 + (ptr_A != NULL) + (ptr_o != NULL))) { /* argv[i] is just a "-A" or "-o" */ continue; } /* copy args other than "-A" or "-o" */ bu_vls_putc(&vls, ' '); c = (char *)argv[i]; while (*c != '\0') { if (*c != 'A' && *c != 'o') { bu_vls_putc(&vls, *c); } c++; } } if (flag_A_attr) { /* args are attribute name/value pairs */ struct bu_attribute_value_set avs; int max_count=0; int remaining_args=0; int new_argc=0; char **new_argv=NULL; struct bu_ptbl *tbl; remaining_args = argc - last_opt - 1; if (remaining_args < 2 || remaining_args%2) { bu_vls_printf(gedp->ged_result_str, "Error: must have even number of arguments (name/value pairs)\n"); bu_vls_free(&vls); return GED_ERROR; } bu_avs_init(&avs, (argc - last_opt)/2, "ged_draw_guts avs"); i = 0; while (i < (size_t)argc) { if (*argv[i] == '-') { i++; continue; } /* this is a name/value pair */ if (flag_o_nonunique == 2) { bu_avs_add_nonunique(&avs, argv[i], argv[i+1]); } else { bu_avs_add(&avs, argv[i], argv[i+1]); } i += 2; } tbl = db_lookup_by_attr(gedp->ged_wdbp->dbip, RT_DIR_REGION | RT_DIR_SOLID | RT_DIR_COMB, &avs, flag_o_nonunique); bu_avs_free(&avs); if (!tbl) { bu_log("Error: db_lookup_by_attr() failed!!\n"); bu_vls_free(&vls); return TCL_ERROR; } if (BU_PTBL_LEN(tbl) < 1) { /* nothing matched, just return */ bu_vls_free(&vls); return TCL_OK; } for (i = 0; i < BU_PTBL_LEN(tbl); i++) { struct directory *dp; dp = (struct directory *)BU_PTBL_GET(tbl, i); bu_vls_putc(&vls, ' '); bu_vls_strcat(&vls, dp->d_namep); } max_count = BU_PTBL_LEN(tbl) + last_opt + 1; bu_ptbl_free(tbl); bu_free((char *)tbl, "ged_draw_guts ptbl"); new_argv = (char **)bu_calloc(max_count+1, sizeof(char *), "ged_draw_guts new_argv"); new_argc = bu_argv_from_string(new_argv, max_count, bu_vls_addr(&vls)); /* First, delete any mention of these objects. * Silently skip any leading options (which start with minus signs). */ for (i = 0; i < (size_t)new_argc; ++i) { /* Skip any options */ if (new_argv[i][0] == '-') { /* If this option requires an argument which was * provided separately (e.g. '-C 0/255/0' instead of * '-C0/255/0'), skip the argument too. */ if (strlen(argv[i]) == 2 && strchr("mxCP", argv[i][1])) { i++; } continue; } dl_erasePathFromDisplay(gedp->ged_gdp->gd_headDisplay, gedp->ged_wdbp->dbip, gedp->ged_free_vlist_callback, new_argv[i], 0, gedp->freesolid); } drawtrees_retval = _ged_drawtrees(gedp, new_argc, (const char **)new_argv, kind, (struct _ged_client_data *)0); bu_vls_free(&vls); bu_free((char *)new_argv, "ged_draw_guts new_argv"); if (drawtrees_retval) { return GED_ERROR; } } else { int empty_display; bu_vls_free(&vls); empty_display = 1; if (BU_LIST_NON_EMPTY(gedp->ged_gdp->gd_headDisplay)) { empty_display = 0; } /* First, delete any mention of these objects. * Silently skip any leading options (which start with minus signs). */ for (i = 0; i < (size_t)argc; ++i) { /* Skip any options */ if (argv[i][0] == '-') { /* If this option requires an argument which was * provided separately (e.g. '-C 0/255/0' instead of * '-C0/255/0'), skip the argument too. */ if (strlen(argv[i]) == 2 && strchr("mxCP", argv[i][1])) { i++; } continue; } dl_erasePathFromDisplay(gedp->ged_gdp->gd_headDisplay, gedp->ged_wdbp->dbip, gedp->ged_free_vlist_callback, argv[i], 0, gedp->freesolid); } /* if our display is non-empty add -R to keep current view */ if (!empty_display) { int new_argc; char **new_argv; new_argc = argc + 1; new_argv = (char **)bu_malloc(new_argc * sizeof(char *), "ged_draw_guts new_argv"); new_argv[0] = bu_strdup("-R"); for (i = 0; i < (size_t)argc; ++i) { new_argv[i + 1] = bu_strdup(argv[i]); } drawtrees_retval = _ged_drawtrees(gedp, new_argc, (const char **)new_argv, kind, (struct _ged_client_data *)0); for (i = 0; i < (size_t)new_argc; ++i) { bu_free(new_argv[i], "ged_draw_guts new_argv[i] - bu_strdup(argv[i])"); } bu_free(new_argv, "ged_draw_guts new_argv"); } else { drawtrees_retval = _ged_drawtrees(gedp, argc, argv, kind, (struct _ged_client_data *)0); } if (drawtrees_retval) { return GED_ERROR; } } #ifdef DEBUG_TIMING elapsedtime = bu_gettime() - elapsedtime; { int seconds = elapsedtime / 1000000; int minutes = seconds / 60; int hours = minutes / 60; minutes = minutes % 60; seconds = seconds %60; bu_vls_printf(gedp->ged_result_str, "Elapsed time: %02d:%02d:%02d\n", hours, minutes, seconds); } #endif return GED_OK; }
struct bu_ptbl * db_lookup_by_attr(struct db_i *dbip, int dir_flags, struct bu_attribute_value_set *avs, int op) { struct bu_attribute_value_set obj_avs; struct directory *dp; struct bu_ptbl *tbl; int match_count = 0; int attr_count; int i, j; int draw; RT_CK_DBI(dbip); if (avs) { BU_CK_AVS(avs); attr_count = avs->count; } else { attr_count = 0; } BU_ALLOC(tbl, struct bu_ptbl); bu_ptbl_init(tbl, 128, "wdb_get_by_attr ptbl_init"); FOR_ALL_DIRECTORY_START(dp, dbip) { if ((dp->d_flags & dir_flags) == 0) continue; /* Skip phony entries */ if (dp->d_addr == RT_DIR_PHONY_ADDR) continue; if (attr_count) { bu_avs_init_empty(&obj_avs); if (db5_get_attributes(dbip, &obj_avs, dp) < 0) { bu_log("ERROR: failed to get attributes for %s\n", dp->d_namep); return (struct bu_ptbl *)NULL; } draw = 0; match_count = 0; for (i = 0; (size_t)i < (size_t)avs->count; i++) { for (j = 0; (size_t)j < (size_t)obj_avs.count; j++) { if (BU_STR_EQUAL(avs->avp[i].name, obj_avs.avp[j].name)) { if (BU_STR_EQUAL(avs->avp[i].value, obj_avs.avp[j].value)) { if (op == 2) { draw = 1; break; } else { match_count++; } } } } if (draw) break; } bu_avs_free(&obj_avs); } else { draw = 1; } if (draw || match_count == attr_count) { bu_ptbl_ins(tbl, (long *)dp); } } FOR_ALL_DIRECTORY_END; return tbl; }
/** * R T _ G E T T R E E S _ M U V E S * * User-called function to add a set of tree hierarchies to the active * set. Includes getting the indicated list of attributes and a * Tcl_HashTable for use with the ORCA man regions. (stashed in the * rt_i structure). * * This function may run in parallel, but is not multiply re-entrant * itself, because db_walk_tree() isn't multiply re-entrant. * * Semaphores used for critical sections in parallel mode: * RT_SEM_TREE* protects rti_solidheads[] lists, d_uses(solids) * RT_SEM_RESULTS protects HeadRegion, mdl_min/max, d_uses(reg), nregions * RT_SEM_WORKER (db_walk_dispatcher, from db_walk_tree) * RT_SEM_STATS nsolids * * INPUTS * rtip - RT instance pointer * attrs - array of pointers (NULL terminated) to strings (attribute names). A corresponding * array of "bu_mro" objects containing the attribute values will be attached to region * structures ("attr_values") * argc - number of trees to get * argv - array of char pointers to the names of the tree tops * ncpus - number of cpus to use * * Returns - * 0 Ordinarily * -1 On major error */ int rt_gettrees_muves(struct rt_i *rtip, const char **attrs, int argc, const char **argv, int ncpus) { register struct soltab *stp; register struct region *regp; Tcl_HashTable *tbl; int prev_sol_count; int i; int num_attrs=0; point_t region_min, region_max; RT_CHECK_RTI(rtip); RT_CK_DBI(rtip->rti_dbip); if (!rtip->needprep) { bu_log("ERROR: rt_gettree() called again after rt_prep!\n"); return(-1); /* FAIL */ } if ( argc <= 0 ) return(-1); /* FAIL */ tbl = (Tcl_HashTable *)bu_malloc( sizeof( Tcl_HashTable ), "rtip->Orca_hash_tbl" ); Tcl_InitHashTable( tbl, TCL_ONE_WORD_KEYS ); rtip->Orca_hash_tbl = (genptr_t)tbl; prev_sol_count = rtip->nsolids; { struct db_tree_state tree_state; tree_state = rt_initial_tree_state; /* struct copy */ tree_state.ts_dbip = rtip->rti_dbip; tree_state.ts_rtip = rtip; tree_state.ts_resp = NULL; /* sanity. Needs to be updated */ if ( attrs ) { if ( rtip->rti_dbip->dbi_version < 5 ) { bu_log( "WARNING: requesting attributes from an old database version (ignored)\n" ); bu_avs_init_empty( &tree_state.ts_attrs ); } else { while ( attrs[num_attrs] ) { num_attrs++; } if ( num_attrs ) { bu_avs_init( &tree_state.ts_attrs, num_attrs, "avs in tree_state" ); num_attrs = 0; while ( attrs[num_attrs] ) { bu_avs_add( &tree_state.ts_attrs, attrs[num_attrs], NULL ); num_attrs++; } } else { bu_avs_init_empty( &tree_state.ts_attrs ); } } } else { bu_avs_init_empty( &tree_state.ts_attrs ); } /* ifdef this out for now, it is only using memory. perhaps a * better way of initiating ORCA stuff can be found. */ #if 0 bu_avs_add( &tree_state.ts_attrs, "ORCA_Comp", (char *)NULL ); #endif i = db_walk_tree( rtip->rti_dbip, argc, argv, ncpus, &tree_state, rt_gettree_region_start, rt_gettree_region_end, rt_gettree_leaf, (genptr_t)tbl ); bu_avs_free( &tree_state.ts_attrs ); } /* DEBUG: Ensure that all region trees are valid */ for ( BU_LIST_FOR( regp, region, &(rtip->HeadRegion) ) ) { RT_CK_REGION(regp); db_ck_tree(regp->reg_treetop); } /* * Eliminate any "dead" solids that parallel code couldn't change. * First remove any references from the region tree, then remove * actual soltab structs from the soltab list. */ for ( BU_LIST_FOR( regp, region, &(rtip->HeadRegion) ) ) { RT_CK_REGION(regp); rt_tree_kill_dead_solid_refs( regp->reg_treetop ); (void)rt_tree_elim_nops( regp->reg_treetop, &rt_uniresource ); } again: RT_VISIT_ALL_SOLTABS_START( stp, rtip ) { RT_CK_SOLTAB(stp); if ( stp->st_aradius <= 0 ) { bu_log("rt_gettrees() cleaning up dead solid '%s'\n", stp->st_dp->d_namep ); rt_free_soltab(stp); /* Can't do rtip->nsolids--, that doubles as max bit number! */ /* The macro makes it hard to regain place, punt */ goto again; } } RT_VISIT_ALL_SOLTABS_END