int db_avs_diff(const struct bu_attribute_value_set *left_set, const struct bu_attribute_value_set *right_set, const struct bn_tol *diff_tol, int (*add_func)(const char *attr_name, const char *attr_val, void *data), int (*del_func)(const char *attr_name, const char *attr_val, void *data), int (*chgd_func)(const char *attr_name, const char *attr_val_left, const char *attr_val_right, void *data), int (*unchgd_func)(const char *attr_name, const char *attr_val, void *data), void *client_data) { int state = DIFF_EMPTY; struct bu_attribute_value_pair *avp; for (BU_AVS_FOR(avp, left_set)) { const char *val2 = bu_avs_get(right_set, avp->name); if (!val2) { if (del_func) {state |= del_func(avp->name, avp->value, client_data);} } else { if (avpp_val_compare(avp->value, val2, diff_tol)) { if (unchgd_func) {state |= unchgd_func(avp->name, avp->value, client_data);} } else { if (chgd_func) {state |= chgd_func(avp->name, avp->value, val2, client_data);} } } } for (BU_AVS_FOR(avp, right_set)) { const char *val1 = bu_avs_get(left_set, avp->name); if (!val1) { if (add_func) {state |= add_func(avp->name, avp->value, client_data);} } } return state; }
/** * This routine will be called by db_walk_tree() once all the solids * in this region have been visited. * * This routine must be prepared to run in parallel. As a result, * note that the details of the solids pointed to by the soltab * pointers in the tree may not be filled in when this routine is * called (due to the way multiple instances of solids are handled). * Therefore, everything which referred to the tree has been moved out * into the serial section. (_rt_tree_region_assign, rt_bound_tree) */ HIDDEN union tree * _rt_gettree_region_end(struct db_tree_state *tsp, const struct db_full_path *pathp, union tree *curtree, void *client_data) { struct region *rp; struct directory *dp = NULL; size_t shader_len=0; struct rt_i *rtip; Tcl_HashTable *tbl = (Tcl_HashTable *)client_data; Tcl_HashEntry *entry; matp_t inv_mat; struct bu_attribute_value_set avs; struct bu_attribute_value_pair *avpp; RT_CK_DBI(tsp->ts_dbip); RT_CK_FULL_PATH(pathp); RT_CK_TREE(curtree); rtip = tsp->ts_rtip; RT_CK_RTI(rtip); RT_CK_RESOURCE(tsp->ts_resp); if (curtree->tr_op == OP_NOP) { /* Ignore empty regions */ return curtree; } BU_ALLOC(rp, struct region); rp->l.magic = RT_REGION_MAGIC; rp->reg_regionid = tsp->ts_regionid; rp->reg_is_fastgen = tsp->ts_is_fastgen; rp->reg_aircode = tsp->ts_aircode; rp->reg_gmater = tsp->ts_gmater; rp->reg_los = tsp->ts_los; dp = (struct directory *)DB_FULL_PATH_CUR_DIR(pathp); if (!dp) return TREE_NULL; bu_avs_init_empty(&avs); if (db5_get_attributes(tsp->ts_dbip, &avs, dp) == 0) { /* copy avs */ bu_avs_init_empty(&(rp->attr_values)); for (BU_AVS_FOR(avpp, &(tsp->ts_attrs))) { bu_avs_add(&(rp->attr_values), avpp->name, bu_avs_get(&avs, avpp->name)); } }
/** * Get an attribute from a bu_avs, like bu_avs_get, but return "--" if * the item is missing, instead of NULL */ static const char * get_attr(const struct bu_attribute_value_set *avp, const char *attribute) { const char *value = bu_avs_get(avp, attribute); return value ? value : "--"; }
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_concat(struct ged *gedp, int argc, const char *argv[]) { struct db_i *newdbp; struct directory *dp; Tcl_HashTable name_tbl; Tcl_HashTable used_names_tbl; Tcl_HashEntry *ptr; Tcl_HashSearch search; struct bu_attribute_value_set g_avs; const char *cp; char *colorTab; struct ged_concat_data cc_data; const char *oldfile; static const char *usage = "[-u] [-t] [-c] [-s|-p] file.g [suffix|prefix]"; int importUnits = 0; int importTitle = 0; int importColorTable = 0; int saveGlobalAttrs = 0; int c; const char *commandName; 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); if (argc < 2) { bu_vls_printf(gedp->ged_result_str, "Usage: %s %s", argv[0], usage); return GED_ERROR; } bu_vls_init(&cc_data.affix); cc_data.copy_mode = 0; commandName = argv[0]; /* process args */ bu_optind = 1; bu_opterr = 0; while ((c=bu_getopt(argc, (char * const *)argv, "utcsp")) != -1) { switch (c) { case 'u': importUnits = 1; break; case 't': importTitle = 1; break; case 'c': importColorTable = 1; break; case 'p': cc_data.copy_mode |= AUTO_PREFIX; break; case 's': cc_data.copy_mode |= AUTO_SUFFIX; break; default: { bu_vls_printf(gedp->ged_result_str, "Usage: %s %s", commandName, usage); bu_vls_free(&cc_data.affix); return GED_ERROR; } } } argc -= bu_optind; argv += bu_optind; if (argc == 0) { bu_vls_printf(gedp->ged_result_str, "Usage: %s %s", commandName, usage); return GED_ERROR; } oldfile = argv[0]; argc--; argv++; if (cc_data.copy_mode) { /* specified suffix or prefix explicitly */ if (cc_data.copy_mode & AUTO_PREFIX) { if (argc == 0 || BU_STR_EQUAL(argv[0], "/")) { cc_data.copy_mode = NO_AFFIX | CUSTOM_PREFIX; } else { (void)bu_vls_strcpy(&cc_data.affix, argv[0]); cc_data.copy_mode |= CUSTOM_PREFIX; } } else if (cc_data.copy_mode & AUTO_SUFFIX) { if (argc == 0 || BU_STR_EQUAL(argv[0], "/")) { cc_data.copy_mode = NO_AFFIX | CUSTOM_SUFFIX; } else { (void)bu_vls_strcpy(&cc_data.affix, argv[0]); cc_data.copy_mode |= CUSTOM_SUFFIX; } } else { bu_vls_free(&cc_data.affix); bu_vls_printf(gedp->ged_result_str, "Usage: %s %s", commandName, usage); return GED_ERROR; } } else { /* no prefix/suffix preference, use prefix */ cc_data.copy_mode |= AUTO_PREFIX; if (argc == 0 || BU_STR_EQUAL(argv[0], "/")) { cc_data.copy_mode = NO_AFFIX | CUSTOM_PREFIX; } else { (void)bu_vls_strcpy(&cc_data.affix, argv[0]); cc_data.copy_mode |= CUSTOM_PREFIX; } } if (db_version(gedp->ged_wdbp->dbip) < 5) { if (bu_vls_strlen(&cc_data.affix) > _GED_V4_MAXNAME-1) { bu_log("ERROR: affix [%s] is too long for v%d\n", bu_vls_addr(&cc_data.affix), db_version(gedp->ged_wdbp->dbip)); bu_vls_free(&cc_data.affix); return GED_ERROR; } } /* open the input file */ if ((newdbp = db_open(oldfile, DB_OPEN_READONLY)) == DBI_NULL) { bu_vls_free(&cc_data.affix); perror(oldfile); bu_vls_printf(gedp->ged_result_str, "%s: Can't open geometry database file %s", commandName, oldfile); return GED_ERROR; } if (db_version(newdbp) > 4 && db_version(gedp->ged_wdbp->dbip) < 5) { bu_vls_free(&cc_data.affix); bu_vls_printf(gedp->ged_result_str, "%s: databases are incompatible, use dbupgrade on %s first", commandName, gedp->ged_wdbp->dbip->dbi_filename); return GED_ERROR; } db_dirbuild(newdbp); cc_data.new_dbip = newdbp; cc_data.old_dbip = gedp->ged_wdbp->dbip; /* visit each directory pointer in the input database */ Tcl_InitHashTable(&name_tbl, TCL_STRING_KEYS); Tcl_InitHashTable(&used_names_tbl, TCL_STRING_KEYS); if (importUnits || importTitle || importColorTable) { saveGlobalAttrs = 1; } FOR_ALL_DIRECTORY_START(dp, newdbp) { if (dp->d_major_type == DB5_MAJORTYPE_ATTRIBUTE_ONLY) { if (saveGlobalAttrs) { if (db5_get_attributes(newdbp, &g_avs, dp)) { bu_vls_printf(gedp->ged_result_str, "%s: Can't get global attributes from %s", commandName, oldfile); return GED_ERROR; } } continue; } copy_object(gedp, dp, newdbp, gedp->ged_wdbp->dbip, &name_tbl, &used_names_tbl, &cc_data); } FOR_ALL_DIRECTORY_END; bu_vls_free(&cc_data.affix); rt_mempurge(&(newdbp->dbi_freep)); /* Free all the directory entries, and close the input database */ db_close(newdbp); if (importColorTable) { colorTab = bu_strdup(bu_avs_get(&g_avs, "regionid_colortable")); db5_import_color_table(colorTab); bu_free(colorTab, "colorTab"); } else if (saveGlobalAttrs) { bu_avs_remove(&g_avs, "regionid_colortable"); } if (importTitle) { if ((cp = bu_avs_get(&g_avs, "title")) != NULL) { char *oldTitle = gedp->ged_wdbp->dbip->dbi_title; gedp->ged_wdbp->dbip->dbi_title = bu_strdup(cp); if (oldTitle) { bu_free(oldTitle, "old title"); } } } else if (saveGlobalAttrs) { bu_avs_remove(&g_avs, "title"); } if (importUnits) { if ((cp = bu_avs_get(&g_avs, "units")) != NULL) { double dd; if (sscanf(cp, "%lf", &dd) != 1 || NEAR_ZERO(dd, VUNITIZE_TOL)) { bu_log("copy_object(%s): improper database, %s object attribute 'units'=%s is invalid\n", oldfile, DB5_GLOBAL_OBJECT_NAME, cp); bu_avs_remove(&g_avs, "units"); } else { gedp->ged_wdbp->dbip->dbi_local2base = dd; gedp->ged_wdbp->dbip->dbi_base2local = 1 / dd; } } } else if (saveGlobalAttrs) { bu_avs_remove(&g_avs, "units"); } if (saveGlobalAttrs) { dp = db_lookup(gedp->ged_wdbp->dbip, DB5_GLOBAL_OBJECT_NAME, LOOKUP_NOISY); db5_update_attributes(dp, &g_avs, gedp->ged_wdbp->dbip); } db_sync(gedp->ged_wdbp->dbip); /* force changes to disk */ /* Free the Hash tables */ ptr = Tcl_FirstHashEntry(&name_tbl, &search); while (ptr) { bu_free((char *)Tcl_GetHashValue(ptr), "new name"); ptr = Tcl_NextHashEntry(&search); } Tcl_DeleteHashTable(&name_tbl); Tcl_DeleteHashTable(&used_names_tbl); return GED_OK; }
/** * R T _ G E T T R E E _ R E G I O N _ E N D * * This routine will be called by db_walk_tree() once all the solids * in this region have been visited. * * This routine must be prepared to run in parallel. As a result, * note that the details of the solids pointed to by the soltab * pointers in the tree may not be filled in when this routine is * called (due to the way multiple instances of solids are handled). * Therefore, everything which referred to the tree has been moved out * into the serial section. (rt_tree_region_assign, rt_bound_tree) */ HIDDEN union tree *rt_gettree_region_end(register struct db_tree_state *tsp, struct db_full_path *pathp, union tree *curtree, genptr_t client_data) { struct region *rp; struct directory *dp; int shader_len=0; struct rt_i *rtip; int i; Tcl_HashTable *tbl = (Tcl_HashTable *)client_data; Tcl_HashEntry *entry; matp_t inv_mat; RT_CK_DBI(tsp->ts_dbip); RT_CK_FULL_PATH(pathp); RT_CK_TREE(curtree); rtip = tsp->ts_rtip; RT_CK_RTI(rtip); RT_CK_RESOURCE(tsp->ts_resp); if ( curtree->tr_op == OP_NOP ) { /* Ignore empty regions */ return curtree; } BU_GETSTRUCT( rp, region ); rp->l.magic = RT_REGION_MAGIC; rp->reg_regionid = tsp->ts_regionid; rp->reg_is_fastgen = tsp->ts_is_fastgen; rp->reg_aircode = tsp->ts_aircode; rp->reg_gmater = tsp->ts_gmater; rp->reg_los = tsp->ts_los; if ( tsp->ts_attrs.count && tsp->ts_attrs.avp ) { rp->attr_values = (struct bu_mro **)bu_calloc( tsp->ts_attrs.count+1, sizeof( struct bu_mro *), "regp->attr_values" ); for ( i=0; i<tsp->ts_attrs.count; i++ ) { rp->attr_values[i] = bu_malloc( sizeof( struct bu_mro ), "rp->attr_values[i]" ); bu_mro_init_with_string( rp->attr_values[i], tsp->ts_attrs.avp[i].value ); } } else { rp->attr_values = (struct bu_mro **)NULL; } rp->reg_mater = tsp->ts_mater; /* struct copy */ if ( tsp->ts_mater.ma_shader ) shader_len = strlen( tsp->ts_mater.ma_shader ); if ( shader_len ) { rp->reg_mater.ma_shader = bu_strdup( tsp->ts_mater.ma_shader ); } else rp->reg_mater.ma_shader = (char *)NULL; rp->reg_name = db_path_to_string( pathp ); dp = (struct directory *)DB_FULL_PATH_CUR_DIR(pathp); if (RT_G_DEBUG&DEBUG_TREEWALK) { bu_log("rt_gettree_region_end() %s\n", rp->reg_name ); rt_pr_tree( curtree, 0 ); } rp->reg_treetop = curtree; rp->reg_all_unions = db_is_tree_all_unions( curtree ); /* Determine material properties */ rp->reg_mfuncs = (char *)0; rp->reg_udata = (char *)0; if ( rp->reg_mater.ma_color_valid == 0 ) rt_region_color_map(rp); /* enter critical section */ bu_semaphore_acquire( RT_SEM_RESULTS ); rp->reg_instnum = dp->d_uses++; /* * Add the region to the linked list of regions. * Positions in the region bit vector are established at this time. */ BU_LIST_INSERT( &(rtip->HeadRegion), &rp->l ); /* Assign bit vector pos. */ rp->reg_bit = rtip->nregions++; /* leave critical section */ bu_semaphore_release( RT_SEM_RESULTS ); if ( tbl && bu_avs_get( &tsp->ts_attrs, "ORCA_Comp" ) ) { int newentry; long int reg_bit = rp->reg_bit; inv_mat = (matp_t)bu_calloc( 16, sizeof( fastf_t ), "inv_mat" ); if ( tsp->ts_mat ) bn_mat_inv( inv_mat, tsp->ts_mat ); else MAT_IDN( inv_mat ); /* enter critical section */ bu_semaphore_acquire( RT_SEM_RESULTS ); entry = Tcl_CreateHashEntry(tbl, (char *)reg_bit, &newentry); Tcl_SetHashValue( entry, (ClientData)inv_mat ); /* leave critical section */ bu_semaphore_release( RT_SEM_RESULTS ); } if ( RT_G_DEBUG & DEBUG_REGIONS ) { bu_log("Add Region %s instnum %d\n", rp->reg_name, rp->reg_instnum); } /* Indicate that we have swiped 'curtree' */ return(TREE_NULL); }