/** * 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 db5_import_attributes(struct bu_attribute_value_set *avs, const struct bu_external *ap) { const char *cp; const char *ep; int count = 0; #if defined(USE_BINARY_ATTRIBUTES) int bcount = 0; /* for the subset of binary attributes */ #endif BU_CK_EXTERNAL(ap); BU_ASSERT_LONG(ap->ext_nbytes, >=, 4); /* First pass -- count number of attributes */ cp = (const char *)ap->ext_buf; ep = (const char *)ap->ext_buf+ap->ext_nbytes; /* Null "name" string (a pair of NULLs) indicates end of attribute * list (for the original ASCII-valued attributes) */ while (*cp != '\0') { if (cp >= ep) { bu_log("db5_import_attributes() ran off end of buffer, database is probably corrupted\n"); return -1; } cp += strlen(cp)+1; /* value */ cp += strlen(cp)+1; /* next name */ count++; } #if defined(USE_BINARY_ATTRIBUTES) /* Do we have binary attributes? If so, they are after the last * ASCII attribute. */ if (ep > (cp+1)) { /* Count binary attrs. */ /* format is: <ascii name> NULL <binary length [network order, must be decoded]> <bytes...> */ size_t abinlen; cp += 2; /* We are now at the first byte of the first binary attribute... */ while (cp != ep) { ++bcount cp += strlen(cp)+1; /* name */ /* The next value is an unsigned integer of variable width * (a_width: DB5HDR_WIDTHCODE_x) so how do we get its * width? We now have a new member of struct bu_external: * 'unsigned char intwid'. Note that the integer * is in network order and must be properly decoded for * the local architecture. */ cp += db5_decode_length(&abinlen, cp, ap->intwid); /* account for the abinlen bytes */ cp += abinlen; } /* now cp should be at the end */ count += bcount; } else { /* step to the end for the sanity check */ ++cp; } /* Ensure we're exactly at the end */ BU_ASSERT_PTR(cp, ==, ep); #else /* Ensure we're exactly at the end */ BU_ASSERT_PTR(cp+1, ==, ep); #endif /* not really needed for AVS_ADD since bu_avs_add will * incrementally allocate as it needs it. but one alloc is better * than many in case there are many attributes. */ bu_avs_init(avs, count, "db5_import_attributes"); /* Second pass -- populate attributes. */ /* Copy the values from the external buffer instead of using them * directly without copying. This presumes ap will not get free'd * before we're done with the avs. */ cp = (const char *)ap->ext_buf; while (*cp != '\0') { const char *name = cp; /* name */ cp += strlen(cp)+1; /* value */ bu_avs_add(avs, name, cp); cp += strlen(cp)+1; /* next name */ } #if defined(USE_BINARY_ATTRIBUTES) /* Do we have binary attributes? If so, they are after the last * ASCII attribute. */ if (ep > (cp+1)) { /* Count binary attrs. */ /* format is: <ascii name> NULL <binary length [network order, must be decoded]> <bytes...> */ size_t abinlen; cp += 2; /* We are now at the first byte of the first binary attribute... */ while (cp != ep) { const char *name = cp; /* name */ cp += strlen(cp)+1; /* name */ cp += db5_decode_length(&abinlen, cp, ap->intwid); /* now decode for the abinlen bytes */ decode_binary_attribute(const size_t len, const char *cp) decod cp += abinlen; } /* now cp should be at the end */ } else {
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; }
/** * Apply a transformation matrix to the specified 'ip' input revolve * object, storing the results in the specified 'op' out pointer or * creating a copy if NULL. */ int rt_revolve_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 rt_revolve_internal *rip, *rop; point_t tmp_vec; if (dbip) RT_CK_DBI(dbip); RT_CK_DB_INTERNAL(ip); RT_CK_RESOURCE(resp); rip = (struct rt_revolve_internal *)ip->idb_ptr; RT_REVOLVE_CK_MAGIC(rip); if (bu_debug&BU_DEBUG_MEM_CHECK) { bu_log("Barrier check at start of revolve_xform():\n"); bu_mem_barriercheck(); } if (op != ip) { RT_DB_INTERNAL_INIT(op); BU_ALLOC(rop, struct rt_revolve_internal); rop->magic = RT_REVOLVE_INTERNAL_MAGIC; bu_vls_init(&rop->sketch_name); bu_vls_vlscat(&rop->sketch_name, &rip->sketch_name); op->idb_ptr = (void *)rop; op->idb_meth = &OBJ[ID_REVOLVE]; op->idb_major_type = DB5_MAJORTYPE_BRLCAD; op->idb_type = ID_REVOLVE; 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 { rop = (struct rt_revolve_internal *)ip->idb_ptr; } MAT4X3PNT(tmp_vec, mat, rip->v3d); VMOVE(rop->v3d, tmp_vec); MAT4X3VEC(tmp_vec, mat, rip->axis3d); VMOVE(rop->axis3d, tmp_vec); V2MOVE(rop->v2d, rip->v2d); V2MOVE(rop->axis2d, rip->axis2d); if (release && ip != op) { rop->skt = rip->skt; rip->skt = (struct rt_sketch_internal *)NULL; rt_db_free_internal(ip); } else if (rip->skt) { rop->skt = rt_copy_sketch(rip->skt); } else { rop->skt = (struct rt_sketch_internal *)NULL; } if (bu_debug&BU_DEBUG_MEM_CHECK) { bu_log("Barrier check at end of revolve_xform():\n"); bu_mem_barriercheck(); } return 0; }
/** * 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