/* * Gets the output from bu_log and appends it to clientdata vls. */ static int output_catch(void *clientdata, void *str) { struct bu_vls *vp = (struct bu_vls *)clientdata; int len; BU_CK_VLS(vp); len = bu_vls_strlen(vp); bu_vls_strcat(vp, (const char *)str); len = bu_vls_strlen(vp) - len; return len; }
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; }
int wdb_track_cmd(void *data, int argc, const char *argv[]) { struct bu_vls log_str = BU_VLS_INIT_ZERO; struct rt_wdb *wdbp = (struct rt_wdb *)data; int retval; if (argc != 15) { bu_log("ERROR: expecting 15 arguments\n"); return TCL_ERROR; } retval = _ged_track(&log_str, wdbp, argv); if (bu_vls_strlen(&log_str) > 0) { bu_log("%s", bu_vls_addr(&log_str)); } switch (retval) { case GED_OK: return TCL_OK; case GED_ERROR: return TCL_ERROR; } /* This should never happen */ return TCL_ERROR; }
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"); } }
/** * Checks for the existence of a specified object. */ int ged_exists(struct ged *gedp, int argc, const char *argv_orig[]) { /* struct directory *dp;*/ static const char *usage = "object"; struct exists_data ed; struct bu_vls message = BU_VLS_INIT_ZERO; int result; char **argv = bu_dup_argv(argc, argv_orig); GED_CHECK_DATABASE_OPEN(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_orig[0], usage); return GED_HELP; } /* if (argc != 2) { bu_vls_printf(gedp->ged_result_str, "Usage: %s %s", argv_orig[0], usage); return GED_ERROR; } */ ed.t_wp = &argv[1]; ed.gedp = gedp; ed.t_wp_op = NULL; ed.message = &message; result = oexpr(t_lex(*(ed.t_wp), &ed), &ed); if (result) bu_vls_printf(gedp->ged_result_str, "1"); else bu_vls_printf(gedp->ged_result_str, "0"); if (bu_vls_strlen(ed.message) > 0) { bu_vls_printf(gedp->ged_result_str, "%s", bu_vls_addr(ed.message)); bu_vls_free(&message); return GED_ERROR; } bu_vls_free(&message); if (*(ed.t_wp) != NULL && *++(ed.t_wp) != NULL) { return GED_ERROR; } else { return GED_OK; } }
HIDDEN int txt_setup(register struct region *rp, struct bu_vls *matparm, void **dpp, const struct mfuncs *mfp, struct rt_i *rtip) { register struct txt_specific *tp; int pixelbytes = 3; BU_CK_VLS(matparm); BU_GET(tp, struct txt_specific); *dpp = tp; bu_vls_init(&tp->tx_name); /* defaults */ tp->tx_w = tp->tx_n = -1; tp->tx_trans_valid = 0; tp->tx_scale[X] = 1.0; tp->tx_scale[Y] = 1.0; tp->tx_mirror = 0; tp->tx_datasrc = 0; /* source is auto-located by default */ tp->tx_binunifp = NULL; tp->tx_mp = NULL; /* load given values */ if (bu_struct_parse(matparm, txt_parse, (char *)tp) < 0) { BU_PUT(tp, struct txt_specific); return -1; } /* validate values */ if (tp->tx_w < 0) tp->tx_w = 512; if (tp->tx_n < 0) tp->tx_n = tp->tx_w; if (tp->tx_trans_valid) rp->reg_transmit = 1; BU_CK_VLS(&tp->tx_name); if (bu_vls_strlen(&tp->tx_name) <= 0) return -1; /* !?! if (tp->tx_name[0] == '\0') return -1; */ /* FAIL, no file */ if (BU_STR_EQUAL(mfp->mf_name, "bwtexture")) pixelbytes = 1; /* load the texture from its datasource */ if (txt_load_datasource(tp, rtip->rti_dbip, tp->tx_w * tp->tx_n * pixelbytes)<0) { bu_log("\nERROR: txt_setup() %s %s could not be loaded [source was %s]\n", rp->reg_name, bu_vls_addr(&tp->tx_name), tp->tx_datasrc==TXT_SRC_OBJECT?"object":tp->tx_datasrc==TXT_SRC_FILE?"file":"auto"); return -1; } if (rdebug & RDEBUG_SHADE) { bu_log("txt_setup: texture loaded! type=%s name=%s\n", tp->tx_datasrc==TXT_SRC_AUTO?"auto":tp->tx_datasrc==TXT_SRC_OBJECT?"object":tp->tx_datasrc==TXT_SRC_FILE?"file":"unknown", bu_vls_addr(&tp->tx_name)); bu_struct_print("texture", txt_parse, (char *)tp); } return 1; /* OK */ }
/** * Export an REVOLVE from internal form to external format. Note that * this means converting all integers to Big-Endian format and * floating point data to IEEE double. * * Apply the transformation to mm units as well. */ int rt_revolve_export5(struct bu_external *ep, const struct rt_db_internal *ip, double local2mm, const struct db_i *dbip) { struct rt_revolve_internal *rip; /* must be double for import and export */ double vec[ELEMENTS_PER_VECT*3 + 1]; unsigned char *ptr; if (dbip) RT_CK_DBI(dbip); RT_CK_DB_INTERNAL(ip); if (ip->idb_type != ID_REVOLVE) return -1; rip = (struct rt_revolve_internal *)ip->idb_ptr; RT_REVOLVE_CK_MAGIC(rip); BU_CK_EXTERNAL(ep); ep->ext_nbytes = SIZEOF_NETWORK_DOUBLE * (ELEMENTS_PER_VECT*3 + 1) + bu_vls_strlen(&rip->sketch_name) + 1; ep->ext_buf = (uint8_t *)bu_calloc(1, ep->ext_nbytes, "revolve external"); ptr = (unsigned char *)ep->ext_buf; /* Since libwdb users may want to operate in units other than mm, * we offer the opportunity to scale the solid (to get it into mm) * on the way out. */ VSCALE(&vec[0*3], rip->v3d, local2mm); VSCALE(&vec[1*3], rip->axis3d, local2mm); VSCALE(&vec[2*3], rip->r, local2mm); vec[9] = rip->ang; bu_cv_htond(ptr, (unsigned char *)vec, ELEMENTS_PER_VECT*3 + 1); ptr += (ELEMENTS_PER_VECT*3 + 1) * SIZEOF_NETWORK_DOUBLE; bu_strlcpy((char *)ptr, bu_vls_addr(&rip->sketch_name), bu_vls_strlen(&rip->sketch_name) + 1); return 0; }
/** * b u _ v l s _ t r i m s p a c e * * Remove leading and trailing white space from a vls string. */ void bu_vls_trimspace( struct bu_vls *vp ) { BU_CK_VLS(vp); /* Remove trailing white space */ while ( isspace( bu_vls_addr(vp)[bu_vls_strlen(vp)-1] ) ) bu_vls_trunc( vp, -1 ); /* Remove leading white space */ while ( isspace( *bu_vls_addr(vp) ) ) bu_vls_nibble( vp, 1 ); }
/** * b u _ v l s _ s t r d u p * * Make an "ordinary" string copy of a vls string. Storage for the * regular string is acquired using malloc. * * The source string is not affected. */ char * bu_vls_strdup(register const struct bu_vls *vp) { register char *str; register size_t len; BU_CK_VLS(vp); len = bu_vls_strlen(vp); str = bu_malloc(len+1, bu_strdup_message ); strncpy(str, bu_vls_addr(vp), len); str[len] = '\0'; /* sanity */ return str; }
/* Test for bu_vls_encode/bu_vls_decode for reversibility: * * 1. encode the input string * 2. decode the encoded string * 3. decoded string should be the same as input * */ int test_encode(const char *str) { int status = 0; int len_s = str ? strlen(str) : 0; int len_d = 0; /* for length of decoded */ int f_wid = 28; /* desired total field width */ struct bu_vls encoded = BU_VLS_INIT_ZERO; struct bu_vls decoded = BU_VLS_INIT_ZERO; bu_vls_encode(&encoded, str); bu_vls_decode(&decoded, bu_vls_addr(&encoded)); /* should be same as input string */ len_d = bu_vls_strlen(&decoded); if (f_wid < len_s) f_wid = len_s + 1; if (f_wid < len_d) f_wid = len_d + 1; if (BU_STR_EQUAL(str, bu_vls_addr(&decoded)) /* && !BU_STR_EQUAL(str, bu_vls_addr(&encoded)) */ ) { /* a hack for str showing '(null)' in printf if zero length */ if (len_s == 0) len_s = 6; printf("{%*s}%*s -> {%*s}%*s [PASS]\n", len_s, str, f_wid - len_s, " ", len_d, bu_vls_addr(&decoded), f_wid - len_d, " " ); } else { /* a hack for str showing '(null)' in printf if zero length */ if (len_s == 0) len_s = 6; printf("{%*s}%*s -> {%*s}%*s [FAIL] (should be: {%s})\n", len_s, str, f_wid - len_s, " ", len_d, bu_vls_addr(&decoded), f_wid - len_d, " ", str ); status = 1; } bu_vls_free(&encoded); bu_vls_free(&decoded); return status; }
double rt_read_timer(char *str, int len) { struct bu_vls vls = BU_VLS_INIT_ZERO; double cpu; int todo; if (!str) return rt_get_timer((struct bu_vls *)0, (double *)0); cpu = rt_get_timer(&vls, (double *)0); todo = bu_vls_strlen(&vls); if (todo > len) todo = len; bu_strlcpy(str, bu_vls_addr(&vls), todo); return cpu; }
int main(int argc, char *argv[]) { int i, j; int db_index; int c; const char **av; struct ged *gedp; bu_opterr = 0; bu_optind = 1; /* Get past command line options. */ while ((c = bu_getopt(argc, argv, "A:a:de:f:g:Gn:N:pP:qrS:t:U:u:vV:W:h?")) != -1) { switch (c) { case 'A': case 'a': case 'e': case 'd': case 'f': case 'g': case 'G': case 'n': case 'N': case 'p': case 'P': case 'q': case 'r': case 'S': case 't': case 'v': case 'V': case 'W': case 'U': case 'u': break; default: bu_exit(1, usage, argv[0]); break; } } if (bu_optind >= argc) { bu_exit(1, usage, argv[0]); } av = (const char **)bu_calloc(argc, sizeof(char *), "av"); db_index = bu_optind; for (i = j = 0; i < argc; ++i) { if (i == db_index) continue; av[j] = argv[i]; ++j; } av[j] = (char *)0; if ((gedp = ged_open("db", argv[db_index], 1)) == GED_NULL) { bu_free((void *)av, "av"); bu_exit(1, usage, argv[0]); } (void)ged_gqa(gedp, j, av); if (bu_vls_strlen(gedp->ged_result_str) > 0) bu_log("%s", bu_vls_addr(gedp->ged_result_str)); ged_close(gedp); if (gedp) BU_PUT(gedp, struct ged); bu_free((void *)av, "av"); return 0; }
void db_update_nref( struct db_i *dbip, struct resource *resp ) { register int i; register struct directory *dp; struct rt_db_internal intern; struct rt_comb_internal *comb; RT_CK_DBI( dbip ); RT_CK_RESOURCE(resp); /* First, clear any existing counts */ for ( i = 0; i < RT_DBNHASH; i++ ) for ( dp = dbip->dbi_Head[i]; dp != DIR_NULL; dp = dp->d_forw ) dp->d_nref = 0; /* Examine all COMB nodes */ for ( i = 0; i < RT_DBNHASH; i++ ) { for ( dp = dbip->dbi_Head[i]; dp != DIR_NULL; dp = dp->d_forw ) { /* handle non-combination objects that reference other objects */ if ( dp->d_major_type == DB5_MAJORTYPE_BRLCAD ) { struct directory *dp2; if ( dp->d_minor_type == DB5_MINORTYPE_BRLCAD_EXTRUDE ) { struct rt_extrude_internal *extr; if ( rt_db_get_internal(&intern, dp, dbip, (fastf_t *)NULL, resp) < 0 ) continue; extr = (struct rt_extrude_internal *)intern.idb_ptr; RT_EXTRUDE_CK_MAGIC( extr ); if ( extr->sketch_name ) { dp2 = db_lookup( dbip, extr->sketch_name, LOOKUP_QUIET ); if ( dp2 != DIR_NULL ) { dp2->d_nref++; } } rt_db_free_internal( &intern, resp ); } else if ( dp->d_minor_type == DB5_MINORTYPE_BRLCAD_DSP ) { struct rt_dsp_internal *dsp; if ( rt_db_get_internal(&intern, dp, dbip, (fastf_t *)NULL, resp) < 0 ) continue; dsp = (struct rt_dsp_internal *)intern.idb_ptr; RT_DSP_CK_MAGIC( dsp ); if ( dsp->dsp_datasrc == RT_DSP_SRC_OBJ && bu_vls_strlen( &dsp->dsp_name) > 0 ) { dp2 = db_lookup( dbip, bu_vls_addr( &dsp->dsp_name ), LOOKUP_QUIET ); if ( dp2 != DIR_NULL ) { dp2->d_nref++; } } rt_db_free_internal( &intern, resp ); } } if ( !(dp->d_flags & DIR_COMB) ) continue; if ( rt_db_get_internal(&intern, dp, dbip, (fastf_t *)NULL, resp) < 0 ) continue; if ( intern.idb_type != ID_COMBINATION ) { bu_log("NOTICE: %s was marked a combination, but isn't one? Clearing flag\n", dp->d_namep); dp->d_flags &= ~DIR_COMB; rt_db_free_internal( &intern, resp ); continue; } comb = (struct rt_comb_internal *)intern.idb_ptr; db_tree_funcleaf( dbip, comb, comb->tree, db_count_refs, (genptr_t)NULL, (genptr_t)NULL, (genptr_t)NULL ); rt_db_free_internal( &intern, resp ); } } }
/** * Called at the start of a run. * * Returns 1 if framebuffer should be opened, else 0. */ int view_init(struct application *ap, char *file, char *UNUSED(obj), int minus_o, int minus_F) { /* * Allocate a scanline for each processor. */ ap->a_hit = rayhit; ap->a_miss = raymiss; ap->a_onehit = 1; /* * Does the user want occlusion checking? * * If so, load and prep. */ if (bu_vls_strlen(&occlusion_objects) != 0) { struct db_i *dbip; int nObjs; const char **objs; int i; bu_log("rtedge: loading occlusion geometry from %s.\n", file); if (Tcl_SplitList(NULL, bu_vls_addr(&occlusion_objects), &nObjs, &objs) == TCL_ERROR) { bu_log("rtedge: occlusion list = %s\n", bu_vls_addr(&occlusion_objects)); bu_exit(EXIT_FAILURE, "rtedge: could not parse occlusion objects list.\n"); } for (i=0; i<nObjs; ++i) { bu_log("rtedge: occlusion object %d = %s\n", i, objs[i]); } if ((dbip = db_open(file, DB_OPEN_READONLY)) == DBI_NULL) bu_exit(EXIT_FAILURE, "rtedge: could not open geometry database file %s.\n", file); RT_CK_DBI(dbip); #if 0 /* FIXME: calling this when db_open()'s mapped file doesn't * fail will cause duplicate directory entries. need to make * sure db_dirbuild rebuilds from scratch or only updates * existing entries when they exist. */ if (db_dirbuild(dbip) < 0) bu_exit(EXIT_FAILURE, "rtedge: could not read database.\n"); #endif occlusion_rtip = rt_new_rti(dbip); /* clones dbip */ for (i=0; i < MAX_PSW; i++) { rt_init_resource(&occlusion_resources[i], i, occlusion_rtip); bn_rand_init(occlusion_resources[i].re_randptr, i); } db_close(dbip); /* releases original dbip */ for (i=0; i<nObjs; ++i) if (rt_gettree(occlusion_rtip, objs[i]) < 0) bu_log("rtedge: gettree failed for %s\n", objs[i]); else bu_log("rtedge: got tree for object %d = %s\n", i, objs[i]); bu_log("rtedge: occlusion rt_gettrees done.\n"); rt_prep(occlusion_rtip); bu_log("rtedge: occlusion prep done.\n"); /* * Create a set of application structures for the occlusion * geometry. Need one per cpu, the upper half does the per- * thread allocation in worker, but that's off limits. */ occlusion_apps = (struct application **)bu_calloc(npsw, sizeof(struct application *), "occlusion application structure array"); for (i=0; i<npsw; ++i) { BU_ALLOC(occlusion_apps[i], struct application); RT_APPLICATION_INIT(occlusion_apps[i]); occlusion_apps[i]->a_rt_i = occlusion_rtip; occlusion_apps[i]->a_resource = (struct resource *)BU_PTBL_GET(&occlusion_rtip->rti_resources, i); occlusion_apps[i]->a_onehit = 1; occlusion_apps[i]->a_hit = occlusion_hit; occlusion_apps[i]->a_miss = occlusion_miss; if (rpt_overlap) occlusion_apps[i]->a_logoverlap = (void (*)(struct application *, const struct partition *, const struct bu_ptbl *, const struct partition *))NULL; else occlusion_apps[i]->a_logoverlap = rt_silent_logoverlap; } bu_log("rtedge: will perform occlusion testing.\n"); /* * If an inclusion mode has not been specified, use the default. */ if (occlusion_mode == OCCLUSION_MODE_NONE) { occlusion_mode = OCCLUSION_MODE_DEFAULT; bu_log("rtedge: occlusion mode = %d\n", occlusion_mode); } if ((occlusion_mode != OCCLUSION_MODE_NONE) && (overlay == OVERLAY_MODE_UNSET)) { bu_log("rtedge: automagically activating overlay mode.\n"); overlay = OVERLAY_MODE_DOIT; } } if (occlusion_mode != OCCLUSION_MODE_NONE && bu_vls_strlen(&occlusion_objects) == 0) { bu_exit(EXIT_FAILURE, "rtedge: occlusion mode set, but no objects were specified.\n"); } /* if non-default/inverted background was requested, swap the * foreground and background colors. */ if (!default_background) { color tmp; tmp[RED] = fgcolor[RED]; tmp[GRN] = fgcolor[GRN]; tmp[BLU] = fgcolor[BLU]; fgcolor[RED] = bgcolor[RED]; fgcolor[GRN] = bgcolor[GRN]; fgcolor[BLU] = bgcolor[BLU]; bgcolor[RED] = tmp[RED]; bgcolor[GRN] = tmp[GRN]; bgcolor[BLU] = tmp[BLU]; } if (minus_o && (overlay || blend)) { /* * Output is to a file stream. Do not allow parallel * processing since we can't seek to the rows. */ RTG.rtg_parallel = 0; bu_log("view_init: deactivating parallelism due to -o option.\n"); /* * The overlay and blend cannot be used in -o mode. Note that * the overlay directive takes precedence, they can't be used * together. */ overlay = 0; blend = 0; bu_log("view_init: deactivating overlay and blending due to -o option.\n"); } if (overlay) bu_log("view_init: will perform simple overlay.\n"); else if (blend) bu_log("view_init: will perform blending.\n"); return minus_F || (!minus_o && !minus_F); /* we need a framebuffer */ }
/* * 'make_pnts' command for importing point-cloud data into a 'pnts' * primitive. * * Input values: * argv[1] object name * argv[2] filename with path * argv[3] point data file format string * argv[4] point data file units string or conversion factor to millimeters * argv[5] default size of each point * */ int ged_make_pnts(struct ged *gedp, int argc, const char *argv[]) { struct directory *dp; struct rt_db_internal internal; rt_pnt_type type; double local2base; unsigned long numPoints = 0; struct rt_pnts_internal *pnts; double defaultSize = 0.0; void *headPoint = NULL; FILE *fp; int temp_string_index = 0; /* index into temp_string, set to first character in temp_string, i.e. the start */ unsigned long int num_doubles_read = 0; /* counters of double read from file */ int current_character_double = 0; /* flag indicating if current character read is part of a double or delimiter */ int previous_character_double = 0; /* flag indicating if previously read character was part of a double or delimiter */ unsigned long int num_characters_read_from_file = 0; /* counter of number of characters read from file */ unsigned long int start_offset_of_current_double = 0; /* character offset from start of file for current double */ int found_double = 0; /* flag indicating if double encountered in file and needs to be processed */ int found_eof = 0; /* flag indicating if end-of-file encountered when reading file */ int done_processing_format_string = 0; /* flag indicating if loop processing format string should be exited */ char *temp_char_ptr = (char *)NULL; int buf = 0; /* raw character read from file */ double temp_double = 0.0; char temp_string[1024]; int temp_string_size = 1024; /* number of characters that can be stored in temp_string including null terminator character */ /* it is expected that the character representation of a double will never exceed this size string */ char *endp = (char *)NULL; struct bu_vls format_string = BU_VLS_INIT_ZERO; size_t format_string_index = 0; unsigned int num_doubles_per_point = 0; void *point = NULL; char **prompt; static const char *usage = "point_cloud_name filename_with_path file_format file_data_units default_point_size"; prompt = &p_make_pnts[0]; 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 > 6) { bu_vls_printf(gedp->ged_result_str, "Usage: %s %s", argv[0], usage); return GED_ERROR; } /* prompt for point-cloud name */ if (argc < 2) { bu_vls_printf(gedp->ged_result_str, "%s", prompt[0]); return GED_MORE; } GED_CHECK_EXISTS(gedp, argv[1], LOOKUP_QUIET, GED_ERROR); /* prompt for data file name with path */ if (argc < 3) { bu_vls_printf(gedp->ged_result_str, "%s", prompt[1]); return GED_MORE; } /* prompt for data file format */ if (argc < 4) { bu_vls_printf(gedp->ged_result_str, "%s", prompt[2]); return GED_MORE; } /* Validate 'point file data format string' and return point-cloud type. */ if (str2type(argv[3], &type, gedp->ged_result_str) == GED_ERROR) { return GED_ERROR; } /* prompt for data file units */ if (argc < 5) { bu_vls_printf(gedp->ged_result_str, "%s", prompt[3]); return GED_MORE; } /* Validate the unit string and return conversion factor to millimeters. */ if (str2mm(argv[4], &local2base, gedp->ged_result_str) == GED_ERROR) { return GED_ERROR; } /* prompt for default point size */ if (argc < 6) { bu_vls_printf(gedp->ged_result_str, "%s", prompt[4]); return GED_MORE; } defaultSize = strtod(argv[5], &endp); if ((endp != argv[5]) && (*endp == '\0')) { /* convert to double success */ if (defaultSize < 0.0) { bu_vls_printf(gedp->ged_result_str, "Default point size '%lf' must be non-negative.\n", defaultSize); return GED_ERROR; } } else { bu_vls_printf(gedp->ged_result_str, "Invalid default point size '%s'\n", argv[5]); return GED_ERROR; } bu_vls_strcat(&format_string, argv[3]); bu_vls_trimspace(&format_string); /* init database structure */ RT_DB_INTERNAL_INIT(&internal); internal.idb_major_type = DB5_MAJORTYPE_BRLCAD; internal.idb_type = ID_PNTS; internal.idb_meth = &OBJ[ID_PNTS]; BU_ALLOC(internal.idb_ptr, struct rt_pnts_internal); /* init internal structure */ pnts = (struct rt_pnts_internal *) internal.idb_ptr; pnts->magic = RT_PNTS_INTERNAL_MAGIC; pnts->scale = defaultSize; pnts->type = type; pnts->count = numPoints; /* set again later */ pnts->point = NULL; /* empty list head */ switch (type) { case RT_PNT_TYPE_PNT: BU_ALLOC(headPoint, struct pnt); BU_LIST_INIT(&(((struct pnt *)headPoint)->l)); num_doubles_per_point = 3; break; case RT_PNT_TYPE_COL: BU_ALLOC(headPoint, struct pnt_color); BU_LIST_INIT(&(((struct pnt_color *)headPoint)->l)); num_doubles_per_point = 6; break; case RT_PNT_TYPE_SCA: BU_ALLOC(headPoint, struct pnt_scale); BU_LIST_INIT(&(((struct pnt_scale *)headPoint)->l)); num_doubles_per_point = 4; break; case RT_PNT_TYPE_NRM: BU_ALLOC(headPoint, struct pnt_normal); BU_LIST_INIT(&(((struct pnt_normal *)headPoint)->l)); num_doubles_per_point = 6; break; case RT_PNT_TYPE_COL_SCA: BU_ALLOC(headPoint, struct pnt_color_scale); BU_LIST_INIT(&(((struct pnt_color_scale *)headPoint)->l)); num_doubles_per_point = 7; break; case RT_PNT_TYPE_COL_NRM: BU_ALLOC(headPoint, struct pnt_color_normal); BU_LIST_INIT(&(((struct pnt_color_normal *)headPoint)->l)); num_doubles_per_point = 9; break; case RT_PNT_TYPE_SCA_NRM: BU_ALLOC(headPoint, struct pnt_scale_normal); BU_LIST_INIT(&(((struct pnt_scale_normal *)headPoint)->l)); num_doubles_per_point = 7; break; case RT_PNT_TYPE_COL_SCA_NRM: BU_ALLOC(headPoint, struct pnt_color_scale_normal); BU_LIST_INIT(&(((struct pnt_color_scale_normal *)headPoint)->l)); num_doubles_per_point = 10; break; } BU_ASSERT_PTR(headPoint, !=, NULL); pnts->point = headPoint; if ((fp=fopen(argv[2], "rb")) == NULL) { bu_vls_printf(gedp->ged_result_str, "Make '%s' failed. ", argv[1]); bu_vls_printf(gedp->ged_result_str, "Could not open file '%s'.\n", argv[2]); bu_vls_free(&format_string); rt_db_free_internal(&internal); return GED_ERROR; } while (!found_eof) { /* points_loop */ /* allocate memory for single point structure for current point-cloud type */ switch (type) { case RT_PNT_TYPE_PNT: BU_ALLOC(point, struct pnt); break; case RT_PNT_TYPE_COL: BU_ALLOC(point, struct pnt_color); break; case RT_PNT_TYPE_SCA: BU_ALLOC(point, struct pnt_scale); break; case RT_PNT_TYPE_NRM: BU_ALLOC(point, struct pnt_normal); break; case RT_PNT_TYPE_COL_SCA: BU_ALLOC(point, struct pnt_color_scale); break; case RT_PNT_TYPE_COL_NRM: BU_ALLOC(point, struct pnt_color_normal); break; case RT_PNT_TYPE_SCA_NRM: BU_ALLOC(point, struct pnt_scale_normal); break; case RT_PNT_TYPE_COL_SCA_NRM: BU_ALLOC(point, struct pnt_color_scale_normal); break; } /* make sure we have something */ BU_ASSERT_PTR(point, !=, NULL); while (!found_eof && !done_processing_format_string) { /* format_string_loop */ char format = '\0'; while (!found_eof && !found_double) { /* find_doubles_loop */ format = bu_vls_addr(&format_string)[format_string_index]; buf = fgetc(fp); num_characters_read_from_file++; if (feof(fp)) { if (ferror(fp)) { perror("ERROR: Problem reading file, system error message"); fclose(fp); bu_vls_printf(gedp->ged_result_str, "Make '%s' failed. ", argv[1]); bu_vls_printf(gedp->ged_result_str, "Unable to read file at byte '%lu'.\n", num_characters_read_from_file); bu_vls_free(&format_string); rt_db_free_internal(&internal); return GED_ERROR; } else { found_eof = 1; } } if (found_eof) { fclose(fp); current_character_double = 0; if (num_doubles_read == 0) { bu_vls_printf(gedp->ged_result_str, "Make '%s' failed. ", argv[1]); bu_vls_printf(gedp->ged_result_str, "No data in file '%s'.\n", argv[2]); bu_vls_free(&format_string); rt_db_free_internal(&internal); return GED_ERROR; } } else { temp_char_ptr = strchr("0123456789.+-eE", buf); if (temp_char_ptr != NULL) { /* character read is part of a double */ current_character_double = 1; } else { current_character_double = 0; } } if (previous_character_double && current_character_double) { if (temp_string_index >= temp_string_size) { fclose(fp); bu_vls_printf(gedp->ged_result_str, "Make '%s' failed. ", argv[1]); bu_vls_printf(gedp->ged_result_str, "String representing double too large, exceeds '%d' character limit. ", temp_string_size - 1); report_import_error_location(num_doubles_read, num_doubles_per_point, start_offset_of_current_double, format, gedp->ged_result_str); bu_vls_free(&format_string); rt_db_free_internal(&internal); return GED_ERROR; } temp_string[temp_string_index] = (char)buf; temp_string_index++; } if (previous_character_double && !current_character_double) { if (temp_string_index >= temp_string_size) { fclose(fp); bu_vls_printf(gedp->ged_result_str, "Make '%s' failed. ", argv[1]); bu_vls_printf(gedp->ged_result_str, "String representing double too large, exceeds '%d' character limit. ", temp_string_size - 1); report_import_error_location(num_doubles_read, num_doubles_per_point, start_offset_of_current_double, format, gedp->ged_result_str); bu_vls_free(&format_string); rt_db_free_internal(&internal); return GED_ERROR; } temp_string[temp_string_index] = '\0'; /* do not convert string to double for format character '?' */ if (format != '?') { temp_double = strtod(temp_string, &endp); if (!((endp != temp_string) && (*endp == '\0'))) { fclose(fp); bu_vls_printf(gedp->ged_result_str, "Make '%s' failed. ", argv[1]); bu_vls_printf(gedp->ged_result_str, "Unable to convert string '%s' to double. ", temp_string); report_import_error_location(num_doubles_read, num_doubles_per_point, start_offset_of_current_double, format, gedp->ged_result_str); bu_vls_free(&format_string); rt_db_free_internal(&internal); return GED_ERROR; } num_doubles_read++; } else { temp_double = 0.0; } temp_string_index = 0; found_double = 1; previous_character_double = current_character_double; } if (!previous_character_double && current_character_double) { temp_string[temp_string_index] = (char)buf; temp_string_index++; start_offset_of_current_double = num_characters_read_from_file; previous_character_double = current_character_double; } } /* loop exits when eof encountered (and/or) double found */ if (found_double) { /* insert double into point structure for current point-cloud type */ /* do not attempt to insert double into point structure for format character '?' */ if (format != '?') { switch (type) { case RT_PNT_TYPE_PNT: INSERT_COORDINATE_INTO_STRUCTURE(pnt, format, (temp_double * local2base)); break; case RT_PNT_TYPE_COL: INSERT_COORDINATE_INTO_STRUCTURE(pnt_color, format, (temp_double * local2base)); INSERT_COLOR_INTO_STRUCTURE(pnt_color, format, temp_double); break; case RT_PNT_TYPE_SCA: INSERT_COORDINATE_INTO_STRUCTURE(pnt_scale, format, (temp_double * local2base)); INSERT_SCALE_INTO_STRUCTURE(pnt_scale, format, (temp_double * local2base)); break; case RT_PNT_TYPE_NRM: INSERT_COORDINATE_INTO_STRUCTURE(pnt_normal, format, (temp_double * local2base)); INSERT_NORMAL_INTO_STRUCTURE(pnt_normal, format, (temp_double * local2base)); break; case RT_PNT_TYPE_COL_SCA: INSERT_COORDINATE_INTO_STRUCTURE(pnt_color_scale, format, (temp_double * local2base)); INSERT_COLOR_INTO_STRUCTURE(pnt_color_scale, format, temp_double); INSERT_SCALE_INTO_STRUCTURE(pnt_color_scale, format, (temp_double * local2base)); break; case RT_PNT_TYPE_COL_NRM: INSERT_COORDINATE_INTO_STRUCTURE(pnt_color_normal, format, (temp_double * local2base)); INSERT_COLOR_INTO_STRUCTURE(pnt_color_normal, format, temp_double); INSERT_NORMAL_INTO_STRUCTURE(pnt_color_normal, format, (temp_double * local2base)); break; case RT_PNT_TYPE_SCA_NRM: INSERT_COORDINATE_INTO_STRUCTURE(pnt_scale_normal, format, (temp_double * local2base)); INSERT_SCALE_INTO_STRUCTURE(pnt_scale_normal, format, (temp_double * local2base)); INSERT_NORMAL_INTO_STRUCTURE(pnt_scale_normal, format, (temp_double * local2base)); break; case RT_PNT_TYPE_COL_SCA_NRM: INSERT_COORDINATE_INTO_STRUCTURE(pnt_color_scale_normal, format, (temp_double * local2base)); INSERT_COLOR_INTO_STRUCTURE(pnt_color_scale_normal, format, temp_double); INSERT_SCALE_INTO_STRUCTURE(pnt_color_scale_normal, format, (temp_double * local2base)); INSERT_NORMAL_INTO_STRUCTURE(pnt_color_scale_normal, format, (temp_double * local2base)); break; } } found_double = 0; /* allows loop to continue */ format_string_index++; if (format_string_index >= bu_vls_strlen(&format_string)) { done_processing_format_string = 1; } } } /* loop exits when eof encountered (and/or) all doubles for * a single point are stored in point structure */ if (done_processing_format_string) { /* push single point structure onto linked-list of points * which makeup the point-cloud. */ switch (type) { case RT_PNT_TYPE_PNT: BU_LIST_PUSH(&(((struct pnt *)headPoint)->l), &((struct pnt *)point)->l); break; case RT_PNT_TYPE_COL: BU_LIST_PUSH(&(((struct pnt_color *)headPoint)->l), &((struct pnt_color *)point)->l); break; case RT_PNT_TYPE_SCA: BU_LIST_PUSH(&(((struct pnt_scale *)headPoint)->l), &((struct pnt_scale *)point)->l); break; case RT_PNT_TYPE_NRM: BU_LIST_PUSH(&(((struct pnt_normal *)headPoint)->l), &((struct pnt_normal *)point)->l); break; case RT_PNT_TYPE_COL_SCA: BU_LIST_PUSH(&(((struct pnt_color_scale *)headPoint)->l), &((struct pnt_color_scale *)point)->l); break; case RT_PNT_TYPE_COL_NRM: BU_LIST_PUSH(&(((struct pnt_color_normal *)headPoint)->l), &((struct pnt_color_normal *)point)->l); break; case RT_PNT_TYPE_SCA_NRM: BU_LIST_PUSH(&(((struct pnt_scale_normal *)headPoint)->l), &((struct pnt_scale_normal *)point)->l); break; case RT_PNT_TYPE_COL_SCA_NRM: BU_LIST_PUSH(&(((struct pnt_color_scale_normal *)headPoint)->l), &((struct pnt_color_scale_normal *)point)->l); break; } numPoints++; format_string_index = 0; done_processing_format_string = 0; } } /* loop exits when eof encountered */ if (num_doubles_read < num_doubles_per_point) { bu_vls_printf(gedp->ged_result_str, "Make '%s' failed. Number of values read inconsistent with point-cloud type ", argv[1]); bu_vls_printf(gedp->ged_result_str, "defined by format string '%V'. The number of values read must be an even ", format_string); bu_vls_printf(gedp->ged_result_str, "multiple of %d but read %lu values.\n", num_doubles_per_point, num_doubles_read); bu_vls_free(&format_string); rt_db_free_internal(&internal); return GED_ERROR; } if (num_doubles_read % num_doubles_per_point) { bu_vls_printf(gedp->ged_result_str, "Make '%s' failed. Number of values read inconsistent with point-cloud type ", argv[1]); bu_vls_printf(gedp->ged_result_str, "defined by format string '%V'. The number of values read must be an even ", format_string); bu_vls_printf(gedp->ged_result_str, "multiple of %d but read %lu values.\n", num_doubles_per_point, num_doubles_read); bu_vls_free(&format_string); rt_db_free_internal(&internal); return GED_ERROR; } pnts->count = numPoints; GED_DB_DIRADD(gedp, dp, argv[1], RT_DIR_PHONY_ADDR, 0, RT_DIR_SOLID, (void *)&internal.idb_type, GED_ERROR); GED_DB_PUT_INTERNAL(gedp, dp, &internal, &rt_uniresource, GED_ERROR); bu_vls_free(&format_string); bu_vls_printf(gedp->ged_result_str, "Make '%s' success, %lu values read, %lu points imported.\n", argv[1], num_doubles_read, numPoints); 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; }
/** * find a new unique name given a list of previously used names, and * the type of naming mode that described what type of affix to use. */ static char * get_new_name(const char *name, struct db_i *dbip, Tcl_HashTable *name_tbl, Tcl_HashTable *used_names_tbl, struct ged_concat_data *cc_data) { struct bu_vls new_name = BU_VLS_INIT_ZERO; Tcl_HashEntry *ptr = NULL; char *aname = NULL; char *ret_name = NULL; int int_new=0; long num=0; RT_CK_DBI(dbip); BU_ASSERT(name_tbl); BU_ASSERT(used_names_tbl); BU_ASSERT(cc_data); if (!name) { bu_log("WARNING: encountered NULL name, renaming to \"UNKNOWN\"\n"); name = "UNKNOWN"; } ptr = Tcl_CreateHashEntry(name_tbl, name, &int_new); if (!int_new) { return (char *)Tcl_GetHashValue(ptr); } do { /* iterate until we find an object name that is not in * use, trying to accommodate the user's requested affix * naming mode. */ bu_vls_trunc(&new_name, 0); if (cc_data->copy_mode & NO_AFFIX) { if (num > 0 && cc_data->copy_mode & CUSTOM_PREFIX) { /* auto-increment prefix */ bu_vls_printf(&new_name, "%ld_", num); } bu_vls_strcat(&new_name, name); if (num > 0 && cc_data->copy_mode & CUSTOM_SUFFIX) { /* auto-increment suffix */ bu_vls_printf(&new_name, "_%ld", num); } } else if (cc_data->copy_mode & CUSTOM_SUFFIX) { /* use custom suffix */ bu_vls_strcpy(&new_name, name); if (num > 0) { bu_vls_printf(&new_name, "_%ld_", num); } bu_vls_vlscat(&new_name, &cc_data->affix); } else if (cc_data->copy_mode & CUSTOM_PREFIX) { /* use custom prefix */ bu_vls_vlscat(&new_name, &cc_data->affix); if (num > 0) { bu_vls_printf(&new_name, "_%ld_", num); } bu_vls_strcat(&new_name, name); } else if (cc_data->copy_mode & AUTO_SUFFIX) { /* use auto-incrementing suffix */ bu_vls_strcat(&new_name, name); bu_vls_printf(&new_name, "_%ld", num); } else if (cc_data->copy_mode & AUTO_PREFIX) { /* use auto-incrementing prefix */ bu_vls_printf(&new_name, "%ld_", num); bu_vls_strcat(&new_name, name); } else { /* no custom suffix/prefix specified, use prefix */ if (num > 0) { bu_vls_printf(&new_name, "_%ld", num); } bu_vls_strcpy(&new_name, name); } /* make sure it fits for v4 */ if (db_version(cc_data->old_dbip) < 5) { if (bu_vls_strlen(&new_name) > _GED_V4_MAXNAME) { bu_log("ERROR: generated new name [%s] is too long (%zu > %d)\n", bu_vls_addr(&new_name), bu_vls_strlen(&new_name), _GED_V4_MAXNAME); } return NULL; } aname = bu_vls_addr(&new_name); num++; } while (db_lookup(dbip, aname, LOOKUP_QUIET) != RT_DIR_NULL || Tcl_FindHashEntry(used_names_tbl, aname) != NULL); /* if they didn't get what they asked for, warn them */ if (num > 1) { if (cc_data->copy_mode & NO_AFFIX) { bu_log("WARNING: unable to import [%s] without an affix, imported as [%s]\n", name, bu_vls_addr(&new_name)); } else if (cc_data->copy_mode & CUSTOM_SUFFIX) { bu_log("WARNING: unable to import [%s] as [%s%s], imported as [%s]\n", name, name, bu_vls_addr(&cc_data->affix), bu_vls_addr(&new_name)); } else if (cc_data->copy_mode & CUSTOM_PREFIX) { bu_log("WARNING: unable to import [%s] as [%s%s], imported as [%s]\n", name, bu_vls_addr(&cc_data->affix), name, bu_vls_addr(&new_name)); } } /* we should now have a unique name. store it in the hash */ ret_name = bu_vls_strgrab(&new_name); Tcl_SetHashValue(ptr, (ClientData)ret_name); (void)Tcl_CreateHashEntry(used_names_tbl, ret_name, &int_new); bu_vls_free(&new_name); return ret_name; }
/* * Given a u, v coordinate within the texture (0 <= u, v <= 1.0), * return a pointer to the relevant pixel. * * Note that .pix files are stored left-to-right, bottom-to-top, * which works out very naturally for the indexing scheme. */ HIDDEN int txt_render(struct application *ap, const struct partition *pp, struct shadework *swp, void *dp) { register struct txt_specific *tp = (struct txt_specific *)dp; fastf_t xmin, xmax, ymin, ymax; int dx, dy; register fastf_t r, g, b; struct uvcoord uvc; long tmp; RT_CK_AP(ap); RT_CHECK_PT(pp); uvc = swp->sw_uv; if (rdebug & RDEBUG_SHADE) bu_log("in txt_render(): du=%g, dv=%g\n", uvc.uv_du, uvc.uv_dv); /* take care of scaling U, V coordinates to get the desired amount * of replication of the texture */ uvc.uv_u *= tp->tx_scale[X]; tmp = uvc.uv_u; uvc.uv_u -= tmp; if (tp->tx_mirror && (tmp & 1)) uvc.uv_u = 1.0 - uvc.uv_u; uvc.uv_v *= tp->tx_scale[Y]; tmp = uvc.uv_v; uvc.uv_v -= tmp; if (tp->tx_mirror && (tmp & 1)) uvc.uv_v = 1.0 - uvc.uv_v; uvc.uv_du /= tp->tx_scale[X]; uvc.uv_dv /= tp->tx_scale[Y]; /* * If no texture file present, or if * texture isn't and can't be read, give debug colors */ if ((bu_vls_strlen(&tp->tx_name) <= 0) || (!tp->tx_mp && !tp->tx_binunifp)) { bu_log("WARNING: texture [%s] could not be read\n", bu_vls_addr(&tp->tx_name)); VSET(swp->sw_color, uvc.uv_u, 0, uvc.uv_v); if (swp->sw_reflect > 0 || swp->sw_transmit > 0) (void)rr_render(ap, pp, swp); return 1; } /* u is left->right index, v is line number bottom->top */ /* Don't filter more than 1/8 of the texture for 1 pixel! */ if (uvc.uv_du > 0.125) uvc.uv_du = 0.125; if (uvc.uv_dv > 0.125) uvc.uv_dv = 0.125; if (uvc.uv_du < 0 || uvc.uv_dv < 0) { bu_log("txt_render uv=%g, %g, du dv=%g %g seg=%s\n", uvc.uv_u, uvc.uv_v, uvc.uv_du, uvc.uv_dv, pp->pt_inseg->seg_stp->st_name); uvc.uv_du = uvc.uv_dv = 0; } xmin = uvc.uv_u - uvc.uv_du; xmax = uvc.uv_u + uvc.uv_du; ymin = uvc.uv_v - uvc.uv_dv; ymax = uvc.uv_v + uvc.uv_dv; if (xmin < 0) xmin = 0; if (ymin < 0) ymin = 0; if (xmax > 1) xmax = 1; if (ymax > 1) ymax = 1; if (rdebug & RDEBUG_SHADE) bu_log("footprint in texture space is (%g %g) <-> (%g %g)\n", xmin * (tp->tx_w-1), ymin * (tp->tx_n-1), xmax * (tp->tx_w-1), ymax * (tp->tx_n-1)); dx = (int)(xmax * (tp->tx_w-1)) - (int)(xmin * (tp->tx_w-1)); dy = (int)(ymax * (tp->tx_n-1)) - (int)(ymin * (tp->tx_n-1)); if (rdebug & RDEBUG_SHADE) bu_log("\tdx = %d, dy = %d\n", dx, dy); if (dx == 0 && dy == 0) { /* No averaging necessary */ register unsigned char *cp=NULL; if (tp->tx_mp) { cp = ((unsigned char *)(tp->tx_mp->buf)) + (int)(ymin * (tp->tx_n-1)) * tp->tx_w * 3 + (int)(xmin * (tp->tx_w-1)) * 3; } else if (tp->tx_binunifp) { cp = ((unsigned char *)(tp->tx_binunifp->u.uint8)) + (int)(ymin * (tp->tx_n-1)) * tp->tx_w * 3 + (int)(xmin * (tp->tx_w-1)) * 3; } else { bu_bomb("sh_text.c -- No texture data found\n"); } r = *cp++; g = *cp++; b = *cp; } else { /* Calculate weighted average of cells in footprint */ fastf_t tot_area = 0.0; fastf_t cell_area; int start_line, stop_line, line; int start_col, stop_col, col; fastf_t xstart, xstop, ystart, ystop; xstart = xmin * (tp->tx_w-1); xstop = xmax * (tp->tx_w-1); ystart = ymin * (tp->tx_n-1); ystop = ymax * (tp->tx_n-1); start_line = ystart; stop_line = ystop; start_col = xstart; stop_col = xstop; r = g = b = 0.0; if (rdebug & RDEBUG_SHADE) { bu_log("\thit in texture space = (%g %g)\n", uvc.uv_u * (tp->tx_w-1), uvc.uv_v * (tp->tx_n-1)); bu_log("\t averaging from (%g %g) to (%g %g)\n", xstart, ystart, xstop, ystop); bu_log("\tcontributions to average:\n"); } for (line = start_line; line <= stop_line; line++) { register unsigned char *cp=NULL; fastf_t line_factor; fastf_t line_upper, line_lower; line_upper = line + 1.0; if (line_upper > ystop) line_upper = ystop; line_lower = line; if (line_lower < ystart) line_lower = ystart; line_factor = line_upper - line_lower; if (tp->tx_mp) { cp = ((unsigned char *)(tp->tx_mp->buf)) + line * tp->tx_w * 3 + (int)(xstart) * 3; } else if (tp->tx_binunifp) { cp = ((unsigned char *)(tp->tx_binunifp->u.uint8)) + line * tp->tx_w * 3 + (int)(xstart) * 3; } else { /* not reachable */ bu_bomb("sh_text.c -- Unable to read datasource\n"); } for (col = start_col; col <= stop_col; col++) { fastf_t col_upper, col_lower; col_upper = col + 1.0; if (col_upper > xstop) col_upper = xstop; col_lower = col; if (col_lower < xstart) col_lower = xstart; cell_area = line_factor * (col_upper - col_lower); tot_area += cell_area; if (rdebug & RDEBUG_SHADE) bu_log("\t %d %d %d weight=%g (from col=%d line=%d)\n", *cp, *(cp+1), *(cp+2), cell_area, col, line); r += (*cp++) * cell_area; g += (*cp++) * cell_area; b += (*cp++) * cell_area; } } r /= tot_area; g /= tot_area; b /= tot_area; } if (rdebug & RDEBUG_SHADE) bu_log(" average: %g %g %g\n", r, g, b); if (!tp->tx_trans_valid) { opaque: VSET(swp->sw_color, r / 255.0, g / 255.0, b / 255.0); if (swp->sw_reflect > 0 || swp->sw_transmit > 0) (void)rr_render(ap, pp, swp); return 1; } /* This circumlocution needed to keep expression simple for Cray, * and others */ if (!EQUAL(r, ((long)tp->tx_transp[0]))) goto opaque; if (!EQUAL(g, ((long)tp->tx_transp[1]))) goto opaque; if (!EQUAL(b, ((long)tp->tx_transp[2]))) goto opaque; /* * Transparency mapping is enabled, and we hit a transparent spot. * Let higher level handle it in reflect/refract code. */ swp->sw_transmit = 1.0; swp->sw_reflect = 0.0; bu_log("leaving txt_render()\n"); if (swp->sw_reflect > 0 || swp->sw_transmit > 0) (void)rr_render(ap, pp, swp); return 1; }
/* * D O _ R E G I O N _ E N D * * Called from db_walk_tree(). * * This routine must be prepared to run in parallel. */ union tree *do_region_end(struct db_tree_state *tsp, const struct db_full_path *pathp, union tree *curtree, genptr_t UNUSED(client_data)) { union tree *ret_tree; struct nmgregion *r; RT_CK_TESS_TOL(tsp->ts_ttol); BN_CK_TOL(tsp->ts_tol); NMG_CK_MODEL(*tsp->ts_m); if (RT_G_DEBUG&DEBUG_TREEWALK || verbose) { char *sofar = db_path_to_string(pathp); bu_log("\ndo_region_end(%d %d%%) %s\n", regions_tried, regions_tried>0 ? (regions_done * 100) / regions_tried : 0, sofar); bu_free(sofar, "path string"); } if (curtree->tr_op == OP_NOP) return curtree; regions_tried++; ret_tree = process_boolean(curtree, tsp, pathp); if ( ret_tree ) r = ret_tree->tr_d.td_r; else r = (struct nmgregion *)NULL; regions_done++; if (r != 0) { FILE *fp_psurf; size_t i; struct bu_vls file_base = BU_VLS_INIT_ZERO; struct bu_vls file = BU_VLS_INIT_ZERO; bu_vls_strcpy(&file_base, prefix); bu_vls_strcat(&file_base, DB_FULL_PATH_CUR_DIR(pathp)->d_namep); /* Dots confuse Jack's Peabody language. Change to '_'. */ for (i = 0; i < file_base.vls_len; i++) if (file_base.vls_str[i] == '.') file_base.vls_str[i] = '_'; /* Write color attribute to .fig figure file. */ if (tsp->ts_mater.ma_color_valid != 0) { fprintf(fp_fig, "\tattribute %s {\n", bu_vls_addr(&file_base)); fprintf(fp_fig, "\t\trgb = (%f, %f, %f);\n", V3ARGS(tsp->ts_mater.ma_color)); fprintf(fp_fig, "\t\tambient = 0.18;\n"); fprintf(fp_fig, "\t\tdiffuse = 0.72;\n"); fprintf(fp_fig, "\t}\n"); } /* Write segment attributes to .fig figure file. */ fprintf(fp_fig, "\tsegment %s_seg {\n", bu_vls_addr(&file_base)); fprintf(fp_fig, "\t\tpsurf=\"%s.pss\";\n", bu_vls_addr(&file_base)); if (tsp->ts_mater.ma_color_valid != 0) fprintf(fp_fig, "\t\tattribute=%s;\n", bu_vls_addr(&file_base)); fprintf(fp_fig, "\t\tsite base->location=trans(0, 0, 0);\n"); fprintf(fp_fig, "\t}\n"); if ( bu_vls_strlen(&base_seg) <= 0 ) { bu_vls_vlscat( &base_seg, &file_base ); } else { fprintf(fp_fig, "\tjoint %s_jt {\n", bu_vls_addr(&file_base)); fprintf(fp_fig, "\t\tconnect %s_seg.base to %s_seg.base;\n", bu_vls_addr(&file_base), bu_vls_addr(&base_seg) ); fprintf(fp_fig, "\t}\n"); } bu_vls_vlscat(&file, &file_base); bu_vls_strcat(&file, ".pss"); /* Required Jack suffix. */ /* Write psurf to .pss file. */ if ((fp_psurf = fopen(bu_vls_addr(&file), "wb")) == NULL) perror(bu_vls_addr(&file)); else { nmg_to_psurf(r, fp_psurf); fclose(fp_psurf); if (verbose) bu_log("*** Wrote %s\n", bu_vls_addr(&file)); } bu_vls_free(&file); /* Also write as UNIX-plot file, if desired */ if ( debug_plots ) { FILE *fp; bu_vls_vlscat(&file, &file_base); bu_vls_strcat(&file, ".pl"); if ((fp = fopen(bu_vls_addr(&file), "wb")) == NULL) perror(bu_vls_addr(&file)); else { struct bu_list vhead; pl_color( fp, (int)(tsp->ts_mater.ma_color[0] * 255), (int)(tsp->ts_mater.ma_color[1] * 255), (int)(tsp->ts_mater.ma_color[2] * 255) ); /* nmg_pl_r( fp, r ); */ BU_LIST_INIT( &vhead ); nmg_r_to_vlist( &vhead, r, 0 ); rt_vlist_to_uplot( fp, &vhead ); fclose(fp); if (verbose) bu_log("*** Wrote %s\n", bu_vls_addr(&file)); } bu_vls_free(&file); } /* NMG region is no longer necessary */ nmg_kr(r); } /* * Dispose of original tree, so that all associated dynamic * memory is released now, not at the end of all regions. * A return of TREE_NULL from this routine signals an error, * so we need to cons up an OP_NOP node to return. */ db_free_tree(curtree, &rt_uniresource); /* Does an nmg_kr() */ BU_ALLOC(curtree, union tree); RT_TREE_INIT(curtree); curtree->tr_op = OP_NOP; return curtree; }
int make_hole(struct rt_wdb *wdbp, /* database to be modified */ point_t hole_start, /* center of start of hole */ vect_t hole_depth, /* depth and direction of hole */ fastf_t hole_radius, /* radius of hole */ int num_objs, /* number of objects that this hole affects */ struct directory **dp) /* array of directory pointers * [num_objs] of objects to * get this hole applied */ { struct bu_vls tmp_name = BU_VLS_INIT_ZERO; int i, base_len, count=0; RT_CHECK_WDB(wdbp); /* make sure we are only making holes in combinations, they do not * have to be regions */ for (i=0; i<num_objs; i++) { RT_CK_DIR(dp[i]); if (!(dp[i]->d_flags & RT_DIR_COMB)) { bu_log("make_hole(): can only make holes in combinations\n"); bu_log("\t%s is not a combination\n", dp[i]->d_namep); return 4; } } /* make a unique name for the RCC we will use (of the form * "make_hole_%d") */ bu_vls_strcat(&tmp_name, "make_hole_"); base_len = bu_vls_strlen(&tmp_name); bu_vls_strcat(&tmp_name, "0"); while ((db_lookup(wdbp->dbip, bu_vls_addr(&tmp_name), LOOKUP_QUIET)) != RT_DIR_NULL) { count++; bu_vls_trunc(&tmp_name, base_len); bu_vls_printf(&tmp_name, "%d", count); } /* build the RCC based on parameters passed in */ if (mk_rcc(wdbp, bu_vls_addr(&tmp_name), hole_start, hole_depth, hole_radius)) { bu_log("Failed to create hole cylinder!!!\n"); bu_vls_free(&tmp_name); return 2; } /* subtract this RCC from each combination in the list passed in */ for (i=0; i<num_objs; i++) { struct rt_db_internal intern; struct rt_comb_internal *comb; union tree *tree; /* get the internal form of the combination */ if (rt_db_get_internal(&intern, dp[i], wdbp->dbip, NULL, wdbp->wdb_resp) < 0) { bu_log("Failed to get %s\n", dp[i]->d_namep); bu_vls_free(&tmp_name); return 3; } comb = (struct rt_comb_internal *)intern.idb_ptr; /* Build a new "subtract" node (will be the root of the new tree) */ BU_ALLOC(tree, union tree); RT_TREE_INIT(tree); tree->tr_b.tb_op = OP_SUBTRACT; tree->tr_b.tb_left = comb->tree; /* subtract from the original tree */ comb->tree = tree; /* Build a node for the RCC to be subtracted */ BU_ALLOC(tree, union tree); RT_TREE_INIT(tree); tree->tr_l.tl_op = OP_DB_LEAF; tree->tr_l.tl_mat = NULL; tree->tr_l.tl_name = bu_strdup(bu_vls_addr(&tmp_name)); /* copy name of RCC */ /* Put the RCC node to the right of the root */ comb->tree->tr_b.tb_right = tree; /* Save the modified combination. This will overwrite the * original combination if wdbp was opened with the * RT_WDB_TYPE_DB_DISK flag. If wdbp was opened with the * RT_WDB_TYPE_DB_INMEM flag, then the combination will be * temporarily over-written in memory only and the disk file * will not be modified. */ wdb_put_internal(wdbp, dp[i]->d_namep, &intern, 1.0); } return 0; }
int make_hole_in_prepped_regions(struct rt_wdb *wdbp, /* database to be modified */ struct rt_i *rtip, /* rt_i pointer for the same database */ point_t hole_start, /* center of start of hole */ vect_t hole_depth, /* depth and direction of hole */ fastf_t radius, /* radius of hole */ struct bu_ptbl *regions) /* list of region structures to which this hole * is to be applied */ { struct bu_vls tmp_name = BU_VLS_INIT_ZERO; size_t i, base_len, count=0; struct directory *dp; struct rt_db_internal intern; struct soltab *stp; RT_CHECK_WDB(wdbp); /* make a unique name for the RCC we will use (of the form "make_hole_%d") */ bu_vls_strcat(&tmp_name, "make_hole_"); base_len = bu_vls_strlen(&tmp_name); bu_vls_strcat(&tmp_name, "0"); while ((db_lookup(wdbp->dbip, bu_vls_addr(&tmp_name), LOOKUP_QUIET)) != RT_DIR_NULL) { count++; bu_vls_trunc(&tmp_name, base_len); bu_vls_printf(&tmp_name, "%zu", count); } /* build the RCC based on parameters passed in */ if (mk_rcc(wdbp, bu_vls_addr(&tmp_name), hole_start, hole_depth, radius)) { bu_log("Failed to create hole cylinder!!!\n"); bu_vls_free(&tmp_name); return 2; } /* lookup the newly created RCC */ dp=db_lookup(wdbp->dbip, bu_vls_addr(&tmp_name), LOOKUP_QUIET); if (dp == RT_DIR_NULL) { bu_log("Failed to lookup RCC (%s) just made by make_hole_in_prepped_regions()!!!\n", bu_vls_addr(&tmp_name)); bu_bomb("Failed to lookup RCC just made by make_hole_in_prepped_regions()!!!\n"); } /* get the internal form of the new RCC */ if (rt_db_get_internal(&intern, dp, wdbp->dbip, NULL, wdbp->wdb_resp) < 0) { bu_log("Failed to get internal form of RCC (%s) just made by make_hole_in_prepped_regions()!!!\n", bu_vls_addr(&tmp_name)); bu_bomb("Failed to get internal form of RCC just made by make_hole_in_prepped_regions()!!!\n"); } /* Build a soltab structure for the new RCC */ BU_ALLOC(stp, struct soltab); stp->l.magic = RT_SOLTAB_MAGIC; stp->l2.magic = RT_SOLTAB2_MAGIC; stp->st_uses = 1; stp->st_dp = dp; stp->st_bit = rtip->nsolids++; /* Add the new soltab structure to the rt_i structure */ rtip->rti_Solids = (struct soltab **)bu_realloc(rtip->rti_Solids, rtip->nsolids * sizeof(struct soltab *), "new rti_Solids"); rtip->rti_Solids[stp->st_bit] = stp; /* actually prep the new RCC */ if (intern.idb_meth->ft_prep(stp, &intern, rtip)) { bu_log("Failed to prep RCC (%s) just made by make_hole_in_prepped_regions()!!!\n", bu_vls_addr(&tmp_name)); bu_bomb("Failed to prep RCC just made by make_hole_in_prepped_regions()!!!\n"); } /* initialize the soltabs list of containing regions */ bu_ptbl_init(&stp->st_regions, BU_PTBL_LEN(regions), "stp->st_regions"); /* Subtract the new RCC from each region structure in the list provided */ for (i=0; i<BU_PTBL_LEN(regions); i++) { struct region *rp; union tree *treep; /* get the next region structure */ rp = (struct region *)BU_PTBL_GET(regions, i); RT_CK_REGION(rp); /* create a tree node for the subtraction operation, this will be the new tree root */ BU_ALLOC(treep, union tree); RT_TREE_INIT(treep); treep->tr_b.tb_op = OP_SUBTRACT; treep->tr_b.tb_left = rp->reg_treetop; /* subtract from the old treetop */ treep->tr_b.tb_regionp = rp; /* make the new node the new treetop */ rp->reg_treetop = treep; /* create a tree node for the new RCC */ BU_ALLOC(treep, union tree); RT_TREE_INIT(treep); treep->tr_a.tu_op = OP_SOLID; treep->tr_a.tu_stp = stp; treep->tr_a.tu_regionp = rp; /* the new RCC gets hung on the right of the subtract node */ rp->reg_treetop->tr_b.tb_right = treep; /* make sure the "all unions" flag is not set on this region */ rp->reg_all_unions = 0; /* Add this region to the list of containing regions for the new RCC */ bu_ptbl_ins(&stp->st_regions, (long *)rp); } /* insert the new RCC soltab structure into the already existing space partitioning tree */ insert_in_bsp(stp, &rtip->rti_CutHead); return 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; }
int main(int ac, char **av) { int fmt = 0; int ret = 0; int ac_offset = 0; const char *in_fmt = NULL; const char *out_fmt = NULL; mime_model_t in_type = MIME_MODEL_UNKNOWN; mime_model_t out_type = MIME_MODEL_UNKNOWN; struct bu_vls in_format = BU_VLS_INIT_ZERO; struct bu_vls in_path = BU_VLS_INIT_ZERO; struct bu_vls out_format = BU_VLS_INIT_ZERO; struct bu_vls out_path = BU_VLS_INIT_ZERO; struct bu_vls log = BU_VLS_INIT_ZERO; struct bu_vls input_opts = BU_VLS_INIT_ZERO; struct bu_vls output_opts = BU_VLS_INIT_ZERO; ac-=(ac>0); av+=(ac>0); // skip program name argv[0] if present ac_offset = (ac > 2) ? 2 : 0; // The last two argv entries must always be the input and output paths /* Handle anything else as options */ option::Stats stats(TopUsage, ac - ac_offset, av); option::Option *options = (option::Option *)bu_calloc(stats.options_max, sizeof(option::Option), "options"); option::Option *buffer= (option::Option *)bu_calloc(stats.buffer_max, sizeof(option::Option), "options"); option::Parser parse(TopUsage, ac - ac_offset, av, options, buffer); /* Now that we've parsed them, start using them */ if (options[HELP] || ac == 0) { if (options[HELP].arg) { int help_type_int = bu_file_mime(options[HELP].arg, MIME_MODEL); switch (help_type_int) { case MIME_MODEL_VND_FASTGEN: option::printUsage(std::cout, Fast4Usage); break; case MIME_MODEL_STL: option::printUsage(std::cout, STLUsage); break; default: option::printUsage(std::cout, TopUsage); break; } } else { option::printUsage(std::cout, TopUsage); // TODO - figure out how to get this info from each plugin to construct this table // on the fly... bu_log("\nSupported formats:\n"); bu_log(" ------------------------------------------------------------\n"); bu_log(" | Extension | File Format | Input | Output |\n"); bu_log(" |----------------------------------------------------------|\n"); bu_log(" | stl | STereoLithography | Yes | Yes |\n"); bu_log(" |------------|---------------------------|--------|--------|\n"); bu_log(" | obj | Wavefront Object | Yes | Yes |\n"); bu_log(" |------------|---------------------------|--------|--------|\n"); bu_log(" | step | STEP (AP203) | Yes | Yes |\n"); bu_log(" |------------|---------------------------|--------|--------|\n"); bu_log(" | iges | Initial Graphics | Yes | No |\n"); bu_log(" | | Exchange Specification | | |\n"); bu_log(" |----------------------------------------------------------|\n"); } goto cleanup; } /* Any args that weren't top level args will get passed to the * format specific arg processing routines, after we use the known * top level options and the path inputs to determine what the file * types in question are. Steps: * * 1. Reassemble the unknown args into strings. */ reassemble_argstr(&input_opts, &output_opts, options[UNKNOWN]); if (bu_vls_strlen(&input_opts) > 0) bu_log("Unknown options (input): %s\n", bu_vls_addr(&input_opts)); if (bu_vls_strlen(&output_opts) > 0) bu_log("Unknown options (output): %s\n", bu_vls_addr(&output_opts)); /* * 2. Use bu_argv_from_string to create new * arrays to be fed to the format specific option parsers.*/ /* TODO - determine whether we want to have a specific option prefix, * such as in- and out-, to identify an option as specific to the * input file format suboption parser only. i.e.: * * --in-tol=1.0 -> --tol=1.0 to the input file's suboptions only * --out-tol=2.0 -> --tol=2.0 to the input file's suboptions only * --tol=1.5 -> --tol=1.5 to both input and output suboptions * * consistent with top level --in-format and --out-format options * */ /* See if we have input and output files specified */ if (!extract_path(&in_path, av[ac-2])) { bu_vls_printf(&log, "Error: no input path identified: %s\n", av[ac-2]); ret = 1; } if (!extract_path(&out_path, av[ac-1])) { bu_vls_printf(&log, "Error: no output path identified: %s\n", av[ac-1]); ret = 1; } /* Make sure we have distinct input and output paths */ if (bu_vls_strlen(&in_path) > 0 && BU_STR_EQUAL(bu_vls_addr(&in_path), bu_vls_addr(&out_path))) { bu_vls_printf(&log, "Error: identical path specified for both input and output: %s\n", bu_vls_addr(&out_path)); ret = 1; } /* Find out what input file type we are dealing with */ if (options[IN_FORMAT]) { in_fmt = options[IN_FORMAT].arg; } else { /* If we aren't overridden by an option, it's worth doing file * introspection to see if the file contents identify the input * type solidly, provided we have that capability.*/ /* fake type introspection for testing: */ //bu_vls_sprintf(&in_format, "step"); } fmt = parse_model_string(&in_format, &log, in_fmt, av[ac-2]); in_type = (fmt < 0) ? MIME_MODEL_UNKNOWN : (mime_model_t)fmt; in_fmt = NULL; /* Identify output file type */ if (options[OUT_FORMAT]) out_fmt = options[OUT_FORMAT].arg; fmt = parse_model_string(&out_format, &log, out_fmt, av[ac-1]); out_type = (fmt < 0) ? MIME_MODEL_UNKNOWN : (mime_model_t)fmt; out_fmt = NULL; /* If we get to this point without knowing both input and output types, we've got a problem */ if (in_type == MIME_MODEL_UNKNOWN) { bu_vls_printf(&log, "Error: no format type identified for input path: %s\n", bu_vls_addr(&in_path)); ret = 1; } if (out_type == MIME_MODEL_UNKNOWN) { bu_vls_printf(&log, "Error: no format type identified for output path: %s\n", bu_vls_addr(&out_path)); ret = 1; } /* If everything isn't OK, we're done - report and clean up memory */ if (ret == 1) goto cleanup; /* If we've gotten this far, we know enough to try to convert. Until we * hook in conversion calls to libgcv, print a summary of the option * parsing results for debugging. */ in_fmt = bu_file_mime_str((int)in_type, MIME_MODEL); out_fmt = bu_file_mime_str((int)out_type, MIME_MODEL); bu_log("Input file format: %s\n", in_fmt); bu_log("Output file format: %s\n", out_fmt); bu_log("Input file path: %s\n", bu_vls_addr(&in_path)); bu_log("Output file path: %s\n", bu_vls_addr(&out_path)); switch (in_type) { case MIME_MODEL_VND_FASTGEN: fast4_arg_process(bu_vls_addr(&input_opts)); break; case MIME_MODEL_STL: stl_arg_process(bu_vls_addr(&input_opts)); default: break; } switch (out_type) { case MIME_MODEL_VND_FASTGEN: fast4_arg_process(bu_vls_addr(&output_opts)); break; case MIME_MODEL_STL: stl_arg_process(bu_vls_addr(&output_opts)); default: break; } /* Clean up */ cleanup: if (bu_vls_strlen(&log) > 0) bu_log("%s", bu_vls_addr(&log)); if (in_fmt) bu_free((char *)in_fmt, "input format string"); if (out_fmt) bu_free((char *)out_fmt, "output format string"); bu_free(options, "free options"); bu_free(buffer, "free buffer"); bu_vls_free(&in_format); bu_vls_free(&in_path); bu_vls_free(&out_format); bu_vls_free(&out_path); bu_vls_free(&log); bu_vls_free(&input_opts); bu_vls_free(&output_opts); return ret; }
/* * F _ N I R T * * Invoke nirt with the current view & stuff */ int dgo_nirt_cmd(struct dg_obj *dgop, struct view_obj *vop, int argc, const char **argv) { const char **vp; FILE *fp_in; FILE *fp_out, *fp_err; #ifndef _WIN32 int ret; size_t sret; int pid, rpid; int retcode; int pipe_in[2]; int pipe_out[2]; int pipe_err[2]; #else HANDLE pipe_in[2], pipe_inDup; HANDLE pipe_out[2], pipe_outDup; HANDLE pipe_err[2], pipe_errDup; STARTUPINFO si; PROCESS_INFORMATION pi; SECURITY_ATTRIBUTES sa; char name[1024]; char line1[2048]; int rem = 2048; #endif int use_input_orig = 0; vect_t center_model; vect_t dir; vect_t cml; int i; struct solid *sp; char line[RT_MAXLINE]; char *val; struct bu_vls vls = BU_VLS_INIT_ZERO; struct bu_vls o_vls = BU_VLS_INIT_ZERO; struct bu_vls p_vls = BU_VLS_INIT_ZERO; struct bu_vls t_vls = BU_VLS_INIT_ZERO; struct bn_vlblock *vbp; struct dg_qray_dataList *ndlp; struct dg_qray_dataList HeadQRayData; int args; args = argc + 20 + 2 + dgo_count_tops((struct solid *)&dgop->dgo_headSolid); dgop->dgo_rt_cmd = (char **)bu_calloc(args, sizeof(char *), "alloc dgo_rt_cmd"); vp = (const char **)&dgop->dgo_rt_cmd[0]; *vp++ = "nirt"; /* swipe x, y, z off the end if present */ if (argc > 3) { double scan[3]; if (sscanf(argv[argc-3], "%lf", &scan[X]) == 1 && sscanf(argv[argc-2], "%lf", &scan[Y]) == 1 && sscanf(argv[argc-1], "%lf", &scan[Z]) == 1) { VMOVE(center_model, scan); use_input_orig = 1; argc -= 3; VSCALE(center_model, center_model, dgop->dgo_wdbp->dbip->dbi_local2base); } } /* Calculate point from which to fire ray */ if (!use_input_orig) { VSET(center_model, -vop->vo_center[MDX], -vop->vo_center[MDY], -vop->vo_center[MDZ]); } VSCALE(cml, center_model, dgop->dgo_wdbp->dbip->dbi_base2local); VMOVEN(dir, vop->vo_rotation + 8, 3); VSCALE(dir, dir, -1.0); bu_vls_printf(&p_vls, "xyz %lf %lf %lf;", cml[X], cml[Y], cml[Z]); bu_vls_printf(&p_vls, "dir %lf %lf %lf; s", dir[X], dir[Y], dir[Z]); i = 0; if (DG_QRAY_GRAPHICS(dgop)) { *vp++ = "-e"; *vp++ = DG_QRAY_FORMAT_NULL; /* first ray ---- returns partitions */ *vp++ = "-e"; *vp++ = DG_QRAY_FORMAT_P; /* ray start, direction, and 's' command */ *vp++ = "-e"; *vp++ = bu_vls_addr(&p_vls); /* second ray ---- returns overlaps */ *vp++ = "-e"; *vp++ = DG_QRAY_FORMAT_O; /* ray start, direction, and 's' command */ *vp++ = "-e"; *vp++ = bu_vls_addr(&p_vls); if (DG_QRAY_TEXT(dgop)) { char *cp; int count = 0; /* get 'r' format now; prepend its' format string with a newline */ val = bu_vls_addr(&dgop->dgo_qray_fmts[0].fmt); /* find first '"' */ while (*val != '"' && *val != '\0') ++val; if (*val == '\0') goto done; else ++val; /* skip first '"' */ /* find last '"' */ cp = (char *)strrchr(val, '"'); if (cp != (char *)NULL) /* found it */ count = cp - val; done: if (*val == '\0') bu_vls_printf(&o_vls, " fmt r \"\\n\" "); else { struct bu_vls tmp = BU_VLS_INIT_ZERO; bu_vls_strncpy(&tmp, val, count); bu_vls_printf(&o_vls, " fmt r \"\\n%V\" ", &tmp); bu_vls_free(&tmp); if (count) val += count + 1; bu_vls_printf(&o_vls, "%s", val); } i = 1; *vp++ = "-e"; *vp++ = bu_vls_addr(&o_vls); } } if (DG_QRAY_TEXT(dgop)) { /* load vp with formats for printing */ for (; dgop->dgo_qray_fmts[i].type != (char)0; ++i) bu_vls_printf(&t_vls, "fmt %c %s; ", dgop->dgo_qray_fmts[i].type, bu_vls_addr(&dgop->dgo_qray_fmts[i].fmt)); *vp++ = "-e"; *vp++ = bu_vls_addr(&t_vls); /* nirt does not like the trailing ';' */ bu_vls_trunc(&t_vls, -2); } /* include nirt script string */ if (bu_vls_strlen(&dgop->dgo_qray_script)) { *vp++ = "-e"; *vp++ = bu_vls_addr(&dgop->dgo_qray_script); } *vp++ = "-e"; *vp++ = bu_vls_addr(&p_vls); for (i = 1; i < argc; i++) *vp++ = argv[i]; *vp++ = dgop->dgo_wdbp->dbip->dbi_filename; dgop->dgo_rt_cmd_len = (char **)vp - (char **)dgop->dgo_rt_cmd; /* Note - dgo_build_tops sets the last vp to (char *)0 */ dgop->dgo_rt_cmd_len += dgo_build_tops((struct solid *)&dgop->dgo_headSolid, vp, (const char **)&dgop->dgo_rt_cmd[args]); if (dgop->dgo_qray_cmd_echo) { /* Print out the command we are about to run */ vp = (const char **)&dgop->dgo_rt_cmd[0]; while (*vp) Tcl_AppendResult(dgop->interp, *vp++, " ", (char *)NULL); Tcl_AppendResult(dgop->interp, "\n", (char *)NULL); } if (use_input_orig) { bu_vls_printf(&vls, "\nFiring from (%lf, %lf, %lf)...\n", center_model[X], center_model[Y], center_model[Z]); Tcl_AppendResult(dgop->interp, bu_vls_addr(&vls), (char *)NULL); bu_vls_free(&vls); } else Tcl_AppendResult(dgop->interp, "\nFiring from view center...\n", (char *)NULL); #ifndef _WIN32 ret = pipe(pipe_in); if (ret < 0) perror("pipe"); ret = pipe(pipe_out); if (ret < 0) perror("pipe"); ret = pipe(pipe_err); if (ret < 0) perror("pipe"); (void)signal(SIGINT, SIG_IGN); if ((pid = fork()) == 0) { /* Redirect stdin, stdout, stderr */ (void)close(0); ret = dup(pipe_in[0]); if (ret < 0) perror("dup"); (void)close(1); ret = dup(pipe_out[1]); if (ret < 0) perror("dup"); (void)close(2); ret = dup(pipe_err[1]); if (ret < 0) perror("dup"); /* close pipes */ (void)close(pipe_in[0]); (void)close(pipe_in[1]); (void)close(pipe_out[0]); (void)close(pipe_out[1]); (void)close(pipe_err[0]); (void)close(pipe_err[1]); for (i = 3; i < 20; i++) (void)close(i); (void)signal(SIGINT, SIG_DFL); (void)execvp(dgop->dgo_rt_cmd[0], dgop->dgo_rt_cmd); perror (dgop->dgo_rt_cmd[0]); exit(16); } /* use fp_in to feed view info to nirt */ (void)close(pipe_in[0]); fp_in = fdopen(pipe_in[1], "w"); /* use fp_out to read back the result */ (void)close(pipe_out[1]); fp_out = fdopen(pipe_out[0], "r"); /* use fp_err to read any error messages */ (void)close(pipe_err[1]); fp_err = fdopen(pipe_err[0], "r"); /* send quit command to nirt */ sret = fwrite("q\n", 1, 2, fp_in); if (sret != 2) bu_log("fwrite failure\n"); (void)fclose(fp_in); #else memset((void *)&si, 0, sizeof(STARTUPINFO)); memset((void *)&pi, 0, sizeof(PROCESS_INFORMATION)); memset((void *)&sa, 0, sizeof(SECURITY_ATTRIBUTES)); sa.nLength = sizeof(sa); sa.bInheritHandle = TRUE; sa.lpSecurityDescriptor = NULL; /* Create a pipe for the child process's STDOUT. */ CreatePipe(&pipe_out[0], &pipe_out[1], &sa, 0); /* Create noninheritable read handle and close the inheritable read handle. */ DuplicateHandle(GetCurrentProcess(), pipe_out[0], GetCurrentProcess(), &pipe_outDup , 0, FALSE, DUPLICATE_SAME_ACCESS); CloseHandle(pipe_out[0]); /* Create a pipe for the child process's STDERR. */ CreatePipe(&pipe_err[0], &pipe_err[1], &sa, 0); /* Create noninheritable read handle and close the inheritable read handle. */ DuplicateHandle(GetCurrentProcess(), pipe_err[0], GetCurrentProcess(), &pipe_errDup , 0, FALSE, DUPLICATE_SAME_ACCESS); CloseHandle(pipe_err[0]); /* The steps for redirecting child process's STDIN: * 1. Save current STDIN, to be restored later. * 2. Create anonymous pipe to be STDIN for child process. * 3. Set STDIN of the parent to be the read handle to the * pipe, so it is inherited by the child process. * 4. Create a noninheritable duplicate of the write handle, * and close the inheritable write handle. */ /* Create a pipe for the child process's STDIN. */ CreatePipe(&pipe_in[0], &pipe_in[1], &sa, 0); /* Duplicate the write handle to the pipe so it is not inherited. */ DuplicateHandle(GetCurrentProcess(), pipe_in[1], GetCurrentProcess(), &pipe_inDup, 0, FALSE, /* not inherited */ DUPLICATE_SAME_ACCESS); CloseHandle(pipe_in[1]); si.cb = sizeof(STARTUPINFO); si.lpReserved = NULL; si.lpReserved2 = NULL; si.cbReserved2 = 0; si.lpDesktop = NULL; si.dwFlags = STARTF_USESTDHANDLES | STARTF_USESHOWWINDOW; si.hStdInput = pipe_in[0]; si.hStdOutput = pipe_out[1]; si.hStdError = pipe_err[1]; si.wShowWindow = SW_HIDE; snprintf(line1, rem, "%s ", dgop->dgo_rt_cmd[0]); rem -= (int)strlen(line1) - 1; for (i = 1; i < dgop->dgo_rt_cmd_len; i++) { /* skip commands */ if (strstr(dgop->dgo_rt_cmd[i], "-e") != NULL) ++i; else { /* append other arguments (i.e. options, file and obj(s)) */ snprintf(name, 1024, "\"%s\" ", dgop->dgo_rt_cmd[i]); if (rem - strlen(name) < 1) { bu_log("Ran out of buffer space!"); bu_free(dgop->dgo_rt_cmd, "free dgo_rt_cmd"); dgop->dgo_rt_cmd = NULL; return TCL_ERROR; } bu_strlcat(line1, name, sizeof(line1)); rem -= (int)strlen(name); } } CreateProcess(NULL, line1, NULL, NULL, TRUE, DETACHED_PROCESS, NULL, NULL, &si, &pi); /* use fp_in to feed view info to nirt */ CloseHandle(pipe_in[0]); fp_in = _fdopen(_open_osfhandle((intptr_t)pipe_inDup, _O_TEXT), "wb"); setmode(fileno(fp_in), O_BINARY); /* send commands down the pipe */ for (i = 1; i < dgop->dgo_rt_cmd_len-2; i++) if (strstr(dgop->dgo_rt_cmd[i], "-e") != NULL) fprintf(fp_in, "%s\n", dgop->dgo_rt_cmd[++i]); /* use fp_out to read back the result */ CloseHandle(pipe_out[1]); fp_out = _fdopen(_open_osfhandle((intptr_t)pipe_outDup, _O_TEXT), "rb"); setmode(fileno(fp_out), O_BINARY); /* use fp_err to read any error messages */ CloseHandle(pipe_err[1]); fp_err = _fdopen(_open_osfhandle((intptr_t)pipe_errDup, _O_TEXT), "rb"); setmode(fileno(fp_err), O_BINARY); /* send quit command to nirt */ fwrite("q\n", 1, 2, fp_in); (void)fclose(fp_in); #endif bu_vls_free(&p_vls); /* use to form "partition" part of nirt command above */ if (DG_QRAY_GRAPHICS(dgop)) { double scan[4]; if (DG_QRAY_TEXT(dgop)) bu_vls_free(&o_vls); /* used to form "overlap" part of nirt command above */ BU_LIST_INIT(&HeadQRayData.l); /* handle partitions */ while (bu_fgets(line, RT_MAXLINE, fp_out) != (char *)NULL) { if (line[0] == '\n') { Tcl_AppendResult(dgop->interp, line+1, (char *)NULL); break; } BU_ALLOC(ndlp, struct dg_qray_dataList); BU_LIST_APPEND(HeadQRayData.l.back, &ndlp->l); if (sscanf(line, "%le %le %le %le", &scan[0], &scan[1], &scan[2], &scan[3]) != 4) break; ndlp->x_in = scan[0]; ndlp->y_in = scan[1]; ndlp->z_in = scan[2]; ndlp->los = scan[3]; } vbp = rt_vlblock_init(); dgo_qray_data_to_vlist(dgop, vbp, &HeadQRayData, dir, 0); bu_list_free(&HeadQRayData.l); dgo_cvt_vlblock_to_solids(dgop, vbp, bu_vls_addr(&dgop->dgo_qray_basename), 0); rt_vlblock_free(vbp); /* handle overlaps */ while (bu_fgets(line, RT_MAXLINE, fp_out) != (char *)NULL) { if (line[0] == '\n') { Tcl_AppendResult(dgop->interp, line+1, (char *)NULL); break; } BU_ALLOC(ndlp, struct dg_qray_dataList); BU_LIST_APPEND(HeadQRayData.l.back, &ndlp->l); if (sscanf(line, "%le %le %le %le", &scan[0], &scan[1], &scan[2], &scan[3]) != 4) break; ndlp->x_in = scan[0]; ndlp->y_in = scan[1]; ndlp->z_in = scan[2]; ndlp->los = scan[3]; } vbp = rt_vlblock_init(); dgo_qray_data_to_vlist(dgop, vbp, &HeadQRayData, dir, 1); bu_list_free(&HeadQRayData.l); dgo_cvt_vlblock_to_solids(dgop, vbp, bu_vls_addr(&dgop->dgo_qray_basename), 0); rt_vlblock_free(vbp); } /* * Notify observers, if any, before generating textual output since * such an act (observer notification) wipes out whatever gets stuffed * into the result. */ dgo_notify(dgop); if (DG_QRAY_TEXT(dgop)) { bu_vls_free(&t_vls); while (bu_fgets(line, RT_MAXLINE, fp_out) != (char *)NULL) Tcl_AppendResult(dgop->interp, line, (char *)NULL); } (void)fclose(fp_out); while (bu_fgets(line, RT_MAXLINE, fp_err) != (char *)NULL) Tcl_AppendResult(dgop->interp, line, (char *)NULL); (void)fclose(fp_err); #ifndef _WIN32 /* Wait for program to finish */ while ((rpid = wait(&retcode)) != pid && rpid != -1) ; /* NULL */ if (retcode != 0) pr_wait_status(dgop->interp, retcode); #else /* Wait for program to finish */ WaitForSingleObject(pi.hProcess, INFINITE); #endif FOR_ALL_SOLIDS(sp, &dgop->dgo_headSolid) sp->s_wflag = DOWN; bu_free(dgop->dgo_rt_cmd, "free dgo_rt_cmd"); dgop->dgo_rt_cmd = NULL; return TCL_OK; }
/* * Given a u, v coordinate within the texture (0 <= u, v <= 1.0), * return the filtered intensity. * * Note that .bw files are stored left-to-right, bottom-to-top, * which works out very naturally for the indexing scheme. */ HIDDEN int bwtxt_render(struct application *ap, const struct partition *pp, struct shadework *swp, void *dp) { register struct txt_specific *tp = (struct txt_specific *)dp; fastf_t xmin, xmax, ymin, ymax; int line; int dx, dy; int x, y; register long bw; struct uvcoord uvc; long tmp; uvc = swp->sw_uv; /* * If no texture file present, or if * texture isn't and can't be read, give debug colors */ if ((bu_vls_strlen(&tp->tx_name) <= 0) || (!tp->tx_mp && !tp->tx_binunifp)) { VSET(swp->sw_color, uvc.uv_u, 0, uvc.uv_v); if (swp->sw_reflect > 0 || swp->sw_transmit > 0) (void)rr_render(ap, pp, swp); return 1; } /* take care of scaling U, V coordinates to get the desired amount * of replication of the texture */ uvc.uv_u *= tp->tx_scale[X]; tmp = uvc.uv_u; uvc.uv_u -= tmp; if (tp->tx_mirror && (tmp & 1)) uvc.uv_u = 1.0 - uvc.uv_u; uvc.uv_v *= tp->tx_scale[Y]; tmp = uvc.uv_v; uvc.uv_v -= tmp; if (tp->tx_mirror && (tmp & 1)) uvc.uv_v = 1.0 - uvc.uv_v; uvc.uv_du /= tp->tx_scale[X]; uvc.uv_dv /= tp->tx_scale[Y]; /* u is left->right index, v is line number bottom->top */ /* Don't filter more than 1/8 of the texture for 1 pixel! */ if (uvc.uv_du > 0.125) uvc.uv_du = 0.125; if (uvc.uv_dv > 0.125) uvc.uv_dv = 0.125; if (uvc.uv_du < 0 || uvc.uv_dv < 0) { bu_log("bwtxt_render uv=%g, %g, du dv=%g %g seg=%s\n", uvc.uv_u, uvc.uv_v, uvc.uv_du, uvc.uv_dv, pp->pt_inseg->seg_stp->st_name); uvc.uv_du = uvc.uv_dv = 0; } xmin = uvc.uv_u - uvc.uv_du; xmax = uvc.uv_u + uvc.uv_du; ymin = uvc.uv_v - uvc.uv_dv; ymax = uvc.uv_v + uvc.uv_dv; if (xmin < 0) xmin = 0; if (ymin < 0) ymin = 0; if (xmax > 1) xmax = 1; if (ymax > 1) ymax = 1; x = xmin * (tp->tx_w-1); y = ymin * (tp->tx_n-1); dx = (xmax - xmin) * (tp->tx_w-1); dy = (ymax - ymin) * (tp->tx_n-1); if (dx < 1) dx = 1; if (dy < 1) dy = 1; bw = 0; for (line = 0; line < dy; line++) { register unsigned char *cp=NULL; register unsigned char *ep; if (tp->tx_mp) { cp = ((unsigned char *)(tp->tx_mp->buf)) + (y+line) * tp->tx_w + x; } else if (tp->tx_binunifp) { cp = ((unsigned char *)(tp->tx_binunifp->u.uint8)) + (y+line) * tp->tx_w + x; } else { /* not reachable */ bu_bomb("sh_text.c -- Unable to read datasource\n"); } ep = cp + dx; while (cp < ep) { bw += *cp++; } } if (!tp->tx_trans_valid) { opaque: VSETALL(swp->sw_color, (bw / 255.0) / (dx*dy)); if (swp->sw_reflect > 0 || swp->sw_transmit > 0) (void)rr_render(ap, pp, swp); return 1; } /* This circumlocution needed to keep expression simple for Cray, * and others */ if (bw / (dx*dy) != ((long)tp->tx_transp[0])) goto opaque; /* * Transparency mapping is enabled, and we hit a transparent spot. * Let higher level handle it in reflect/refract code. */ swp->sw_transmit = 1.0; swp->sw_reflect = 0.0; if (swp->sw_reflect > 0 || swp->sw_transmit > 0) (void)rr_render(ap, pp, swp); return 1; }
/* * D O _ R E G I O N _ E N D * * Called from db_walk_tree(). * * This routine must be prepared to run in parallel. */ union tree *do_region_end(register struct db_tree_state *tsp, struct db_full_path *pathp, union tree *curtree, genptr_t client_data) { union tree *ret_tree; struct nmgregion *r; struct bu_list vhead; RT_CK_TESS_TOL(tsp->ts_ttol); BN_CK_TOL(tsp->ts_tol); NMG_CK_MODEL(*tsp->ts_m); BU_LIST_INIT(&vhead); if (RT_G_DEBUG&DEBUG_TREEWALK || verbose) { char *sofar = db_path_to_string(pathp); bu_log("\ndo_region_end(%d %d%%) %s\n", regions_tried, regions_tried>0 ? (regions_done * 100) / regions_tried : 0, sofar); bu_free(sofar, "path string"); } if (curtree->tr_op == OP_NOP) return curtree; regions_tried++; /* Begin bomb protection */ if ( ncpu == 1 ) { if ( BU_SETJUMP ) { /* Error, bail out */ BU_UNSETJUMP; /* Relinquish the protection */ /* Sometimes the NMG library adds debugging bits when * it detects an internal error, before bombing out. */ rt_g.NMG_debug = NMG_debug; /* restore mode */ /* Release the tree memory & input regions */ db_free_tree(curtree, &rt_uniresource); /* Does an nmg_kr() */ /* Get rid of (m)any other intermediate structures */ if ( (*tsp->ts_m)->magic != -1L ) nmg_km(*tsp->ts_m); /* Now, make a new, clean model structure for next pass. */ *tsp->ts_m = nmg_mm(); goto out; } } (void)nmg_model_fuse(*tsp->ts_m, tsp->ts_tol); ret_tree = nmg_booltree_evaluate(curtree, tsp->ts_tol, &rt_uniresource); /* librt/nmg_bool.c */ BU_UNSETJUMP; /* Relinquish the protection */ if ( ret_tree ) r = ret_tree->tr_d.td_r; else r = (struct nmgregion *)NULL; regions_done++; if (r != 0) { FILE *fp_psurf; int i; struct bu_vls file_base; struct bu_vls file; bu_vls_init(&file_base); bu_vls_init(&file); bu_vls_strcpy(&file_base, prefix); bu_vls_strcat(&file_base, DB_FULL_PATH_CUR_DIR(pathp)->d_namep); /* Dots confuse Jack's Peabody language. Change to '_'. */ for (i = 0; i < file_base.vls_len; i++) if (file_base.vls_str[i] == '.') file_base.vls_str[i] = '_'; /* Write color attribute to .fig figure file. */ if (tsp->ts_mater.ma_color_valid != 0) { fprintf(fp_fig, "\tattribute %s {\n", bu_vls_addr(&file_base)); fprintf(fp_fig, "\t\trgb = (%f, %f, %f);\n", V3ARGS(tsp->ts_mater.ma_color)); fprintf(fp_fig, "\t\tambient = 0.18;\n"); fprintf(fp_fig, "\t\tdiffuse = 0.72;\n"); fprintf(fp_fig, "\t}\n"); } /* Write segment attributes to .fig figure file. */ fprintf(fp_fig, "\tsegment %s_seg {\n", bu_vls_addr(&file_base)); fprintf(fp_fig, "\t\tpsurf=\"%s.pss\";\n", bu_vls_addr(&file_base)); if (tsp->ts_mater.ma_color_valid != 0) fprintf(fp_fig, "\t\tattribute=%s;\n", bu_vls_addr(&file_base)); fprintf(fp_fig, "\t\tsite base->location=trans(0, 0, 0);\n"); fprintf(fp_fig, "\t}\n"); if ( bu_vls_strlen(&base_seg) <= 0 ) { bu_vls_vlscat( &base_seg, &file_base ); } else { fprintf(fp_fig, "\tjoint %s_jt {\n", bu_vls_addr(&file_base)); fprintf(fp_fig, "\t\tconnect %s_seg.base to %s_seg.base;\n", bu_vls_addr(&file_base), bu_vls_addr(&base_seg) ); fprintf(fp_fig, "\t}\n"); } bu_vls_vlscat(&file, &file_base); bu_vls_strcat(&file, ".pss"); /* Required Jack suffix. */ /* Write psurf to .pss file. */ if ((fp_psurf = fopen(bu_vls_addr(&file), "wb")) == NULL) perror(bu_vls_addr(&file)); else { nmg_to_psurf(r, fp_psurf); fclose(fp_psurf); if (verbose) bu_log("*** Wrote %s\n", bu_vls_addr(&file)); } bu_vls_free(&file); /* Also write as UNIX-plot file, if desired */ if ( debug_plots ) { FILE *fp; bu_vls_vlscat(&file, &file_base); bu_vls_strcat(&file, ".pl"); if ((fp = fopen(bu_vls_addr(&file), "wb")) == NULL) perror(bu_vls_addr(&file)); else { struct bu_list vhead; pl_color( fp, (int)(tsp->ts_mater.ma_color[0] * 255), (int)(tsp->ts_mater.ma_color[1] * 255), (int)(tsp->ts_mater.ma_color[2] * 255) ); /* nmg_pl_r( fp, r ); */ BU_LIST_INIT( &vhead ); nmg_r_to_vlist( &vhead, r, 0 ); rt_vlist_to_uplot( fp, &vhead ); fclose(fp); if (verbose) bu_log("*** Wrote %s\n", bu_vls_addr(&file)); } bu_vls_free(&file); } /* NMG region is no longer necessary */ nmg_kr(r); } /* * Dispose of original tree, so that all associated dynamic * memory is released now, not at the end of all regions. * A return of TREE_NULL from this routine signals an error, * so we need to cons up an OP_NOP node to return. */ db_free_tree(curtree, &rt_uniresource); /* Does an nmg_kr() */ out: BU_GETUNION(curtree, tree); curtree->magic = RT_TREE_MAGIC; curtree->tr_op = OP_NOP; return(curtree); }
/* * Given a u, v coordinate within the texture (0 <= u, v <= 1.0), * compute a new surface normal. * For now we come up with a local coordinate system, and * make bump perturbations from the red and blue channels of * an RGB image. * * Note that .pix files are stored left-to-right, bottom-to-top, * which works out very naturally for the indexing scheme. */ HIDDEN int bmp_render(struct application *ap, const struct partition *pp, struct shadework *swp, void *dp) { register struct txt_specific *tp = (struct txt_specific *)dp; unsigned char *cp=NULL; fastf_t pertU, pertV; vect_t y; /* world coordinate axis vectors */ vect_t u, v; /* surface coord system vectors */ int i, j; /* bump map pixel indices */ /* * If no texture file present, or if * texture isn't and can't be read, give debug color. */ if ((bu_vls_strlen(&tp->tx_name) <= 0) || (!tp->tx_mp && !tp->tx_binunifp)) { VSET(swp->sw_color, swp->sw_uv.uv_u, 0, swp->sw_uv.uv_v); if (swp->sw_reflect > 0 || swp->sw_transmit > 0) (void)rr_render(ap, pp, swp); return 1; } /* u is left->right index, v is line number bottom->top */ if (swp->sw_uv.uv_u < 0 || swp->sw_uv.uv_u > 1 || swp->sw_uv.uv_v < 0 || swp->sw_uv.uv_v > 1) { bu_log("bmp_render: bad u, v=%g, %g du, dv=%g, %g seg=%s\n", swp->sw_uv.uv_u, swp->sw_uv.uv_v, swp->sw_uv.uv_du, swp->sw_uv.uv_dv, pp->pt_inseg->seg_stp->st_name); VSET(swp->sw_color, 0, 1, 0); if (swp->sw_reflect > 0 || swp->sw_transmit > 0) (void)rr_render(ap, pp, swp); return 1; } /* Find a local coordinate system */ VSET(y, 0, 1, 0); VCROSS(u, y, swp->sw_hit.hit_normal); VUNITIZE(u); VCROSS(v, swp->sw_hit.hit_normal, u); /* Find our RGB value */ i = swp->sw_uv.uv_u * (tp->tx_w-1); j = swp->sw_uv.uv_v * (tp->tx_n-1); if (tp->tx_mp) { cp = ((unsigned char *)(tp->tx_mp->buf)) + (j) * tp->tx_w * 3 + i * 3; } else if (tp->tx_binunifp) { cp = ((unsigned char *)(tp->tx_binunifp->u.uint8)) + (j) * tp->tx_w * 3 + i * 3; } else { /* not reachable */ bu_bomb("sh_text.c -- Unreachable code reached while reading datasource\n"); } pertU = ((fastf_t)(*cp) - 128.0) / 128.0; pertV = ((fastf_t)(*(cp+2)) - 128.0) / 128.0; if (rdebug&RDEBUG_LIGHT) { VPRINT("normal", swp->sw_hit.hit_normal); VPRINT("u", u); VPRINT("v", v); bu_log("cu = %d, cv = %d\n", *cp, *(cp+2)); bu_log("pertU = %g, pertV = %g\n", pertU, pertV); } VJOIN2(swp->sw_hit.hit_normal, swp->sw_hit.hit_normal, pertU, u, pertV, v); VUNITIZE(swp->sw_hit.hit_normal); if (rdebug&RDEBUG_LIGHT) { VPRINT("after", swp->sw_hit.hit_normal); } if (swp->sw_reflect > 0 || swp->sw_transmit > 0) (void)rr_render(ap, pp, swp); return 1; }
int ged_dup(struct ged *gedp, int argc, const char *argv[]) { struct db_i *newdbp = DBI_NULL; struct directory **dirp0 = (struct directory **)NULL; struct dir_check_stuff dcs; static const char *usage = "file.g prefix"; GED_CHECK_DATABASE_OPEN(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; } bu_vls_trunc(&gedp->ged_wdbp->wdb_prestr, 0); if (argc == 3) (void)bu_vls_strcpy(&gedp->ged_wdbp->wdb_prestr, argv[2]); gedp->ged_wdbp->wdb_num_dups = 0; if (db_version(gedp->ged_wdbp->dbip) < 5) { if ((gedp->ged_wdbp->wdb_ncharadd = bu_vls_strlen(&gedp->ged_wdbp->wdb_prestr)) > 12) { gedp->ged_wdbp->wdb_ncharadd = 12; bu_vls_trunc(&gedp->ged_wdbp->wdb_prestr, 12); } } else { gedp->ged_wdbp->wdb_ncharadd = bu_vls_strlen(&gedp->ged_wdbp->wdb_prestr); } /* open the input file */ if ((newdbp = db_open(argv[1], DB_OPEN_READONLY)) == DBI_NULL) { perror(argv[1]); bu_vls_printf(gedp->ged_result_str, "dup: Cannot open geometry database file %s", argv[1]); return GED_ERROR; } bu_vls_printf(gedp->ged_result_str, "\n*** Comparing %s with %s for duplicate names\n", gedp->ged_wdbp->dbip->dbi_filename, argv[1]); if (gedp->ged_wdbp->wdb_ncharadd) { bu_vls_printf(gedp->ged_result_str, " For comparison, all names in %s were prefixed with: %s\n", argv[1], bu_vls_addr(&gedp->ged_wdbp->wdb_prestr)); } /* Get array to hold names of duplicates */ if ((dirp0 = _ged_getspace(gedp->ged_wdbp->dbip, 0)) == (struct directory **) 0) { bu_vls_printf(gedp->ged_result_str, "f_dup: unable to get memory\n"); db_close(newdbp); return GED_ERROR; } /* Scan new database for overlaps */ dcs.main_dbip = gedp->ged_wdbp->dbip; dcs.wdbp = gedp->ged_wdbp; dcs.dup_dirp = dirp0; if (db_version(newdbp) < 5) { if (db_scan(newdbp, dup_dir_check, 0, (void *)&dcs) < 0) { bu_vls_printf(gedp->ged_result_str, "dup: db_scan failure"); bu_free((void *)dirp0, "_ged_getspace array"); db_close(newdbp); return GED_ERROR; } } else { if (db5_scan(newdbp, dup_dir_check5, (void *)&dcs) < 0) { bu_vls_printf(gedp->ged_result_str, "dup: db_scan failure"); bu_free((void *)dirp0, "_ged_getspace array"); db_close(newdbp); return GED_ERROR; } } rt_mempurge(&(newdbp->dbi_freep)); /* didn't really build a directory */ _ged_vls_col_pr4v(gedp->ged_result_str, dirp0, (int)(dcs.dup_dirp - dirp0), 0); bu_vls_printf(gedp->ged_result_str, "\n ----- %d duplicate names found -----", gedp->ged_wdbp->wdb_num_dups); bu_free((void *)dirp0, "_ged_getspace array"); db_close(newdbp); return GED_OK; }