int db_string_to_path(struct db_full_path *pp, const struct db_i *dbip, const char *str) { char *cp; char *slashp; struct directory *dp; char *copy; size_t nslash = 0; int ret = 0; size_t len; RT_CK_DBI(dbip); /* assume NULL str is '/' */ if (!str) { db_full_path_init(pp); return 0; } while (*str == '/') str++; /* strip off leading slashes */ if (*str == '\0') { /* Path of a lone slash */ db_full_path_init(pp); return 0; } copy = bu_strdup(str); /* eliminate all trailing slashes */ len = strlen(copy); while (copy[len - 1] == '/') { copy[len - 1] = '\0'; --len; } cp = copy; while (*cp) { if ((slashp = strchr(cp, '/')) == NULL) break; nslash++; cp = slashp+1; } /* Make a path structure just big enough */ pp->magic = DB_FULL_PATH_MAGIC; pp->fp_maxlen = pp->fp_len = nslash+1; pp->fp_names = (struct directory **)bu_malloc( pp->fp_maxlen * sizeof(struct directory *), "db_string_to_path path array"); pp->fp_bool = (int *)bu_calloc(pp->fp_maxlen, sizeof(int), "db_string_to_path bool array"); pp->fp_mat = (matp_t *)bu_calloc(pp->fp_maxlen, sizeof(matp_t), "db_string_to_path mat array"); /* Build up path array */ cp = copy; nslash = 0; while (*cp) { if ((slashp = strchr(cp, '/')) == NULL) { /* Last element of string, has no trailing slash */ slashp = cp + strlen(cp) - 1; } else { *slashp = '\0'; } if ((dp = db_lookup(dbip, cp, LOOKUP_NOISY)) == RT_DIR_NULL) { bu_log("db_string_to_path() of '%s' failed on '%s'\n", str, cp); ret = -1; /* FAILED */ /* Fall through, storing null dp in this location */ } pp->fp_names[nslash++] = dp; cp = slashp+1; } BU_ASSERT_SIZE_T(nslash, ==, pp->fp_len); bu_free(copy, "db_string_to_path() duplicate string"); return ret; }
static int plot_shaded_eval( struct ged *gedp, const char *path_name, struct _ged_client_data *dgcdp) { int ret; const char *av[3]; const char *tmp_basename = "tmp_shaded_eval_obj"; char *brep_name; /* make a name for the temp brep */ av[0] = "make_name"; av[1] = tmp_basename; ged_make_name(gedp, 2, (const char **)av); brep_name = bu_vls_strdup(gedp->ged_result_str); bu_vls_trunc(gedp->ged_result_str, 0); /* create temp evaluated brep from named object */ av[0] = "brep"; av[1] = path_name; av[2] = brep_name; ret = ged_brep(gedp, 3, av); if (ret == GED_OK) { int brep_made = 0; struct db_tree_state ts; struct rt_db_internal brep_intern; struct db_full_path input_path, brep_path; RT_DB_INTERNAL_INIT(&brep_intern); db_full_path_init(&input_path); db_full_path_init(&brep_path); /* get brep internal */ ret = get_path_and_state(&ts, &brep_path, brep_name, gedp); if (ret == GED_OK) { struct directory *dp = DB_FULL_PATH_CUR_DIR(&brep_path); if (dp->d_flags & RT_DIR_COMB) { ret = rt_db_get_internal(&brep_intern, dp, ts.ts_dbip, NULL, ts.ts_resp); } else { ret = rt_db_get_internal(&brep_intern, dp, ts.ts_dbip, ts.ts_mat, ts.ts_resp); } if (ret >= 0) { brep_made = 1; } db_free_full_path(&brep_path); } /* plot brep, but use the path and state of the input object */ if (brep_made) { ret = get_path_and_state(&ts, &input_path, path_name, gedp); if (ret == GED_OK) { plot_shaded(&ts, &input_path, &brep_intern, dgcdp); rt_db_free_internal(&brep_intern); db_free_full_path(&input_path); } } /* kill temp brep */ av[0] = "kill"; av[1] = brep_name; ged_kill(gedp, 2, av); } bu_free((char *)brep_name, "vls_strdup"); return ret; }
/** * When performing "ev" on a region, consider whether to process the * whole subtree recursively. * * Normally, say "yes" to all regions by returning 0. * * Check for special case: a region of one solid, which can be * directly drawn as polygons without going through NMGs. If we draw * it here, then return -1 to signal caller to ignore further * processing of this region. A hack to view polygonal models * (converted from FASTGEN) more rapidly. */ static int draw_nmg_region_start(struct db_tree_state *tsp, const struct db_full_path *pathp, const struct rt_comb_internal *combp, void *client_data) { union tree *tp; struct directory *dp; struct rt_db_internal intern; mat_t xform; matp_t matp; struct bu_list vhead; struct _ged_client_data *dgcdp = (struct _ged_client_data *)client_data; if (RT_G_DEBUG&DEBUG_TREEWALK) { char *sofar = db_path_to_string(pathp); bu_vls_printf(dgcdp->gedp->ged_result_str, "nmg_region_start(%s)\n", sofar); bu_free((void *)sofar, "path string"); rt_pr_tree(combp->tree, 1); db_pr_tree_state(tsp); } RT_CK_DBI(tsp->ts_dbip); RT_CK_RESOURCE(tsp->ts_resp); BU_LIST_INIT(&vhead); RT_CK_COMB(combp); tp = combp->tree; if (!tp) return -1; RT_CK_TREE(tp); if (tp->tr_l.tl_op != OP_DB_LEAF) return 0; /* proceed as usual */ /* The subtree is a single node. It may be a combination, though */ /* Fetch by name, check to see if it's an easy type */ dp = db_lookup(tsp->ts_dbip, tp->tr_l.tl_name, LOOKUP_NOISY); if (!dp) return 0; /* proceed as usual */ if (!bn_mat_is_identity(tsp->ts_mat)) { if (tp->tr_l.tl_mat) { matp = xform; bn_mat_mul(xform, tsp->ts_mat, tp->tr_l.tl_mat); } else { matp = tsp->ts_mat; } } else { if (tp->tr_l.tl_mat) { matp = tp->tr_l.tl_mat; } else { matp = (matp_t)NULL; } } if (rt_db_get_internal(&intern, dp, tsp->ts_dbip, matp, &rt_uniresource) < 0) return 0; /* proceed as usual */ switch (intern.idb_type) { case ID_POLY: { if (RT_G_DEBUG&DEBUG_TREEWALK) { bu_log("fastpath draw ID_POLY %s\n", dp->d_namep); } if (dgcdp->draw_wireframes) { (void)rt_pg_plot(&vhead, &intern, tsp->ts_ttol, tsp->ts_tol, NULL); } else { (void)rt_pg_plot_poly(&vhead, &intern, tsp->ts_ttol, tsp->ts_tol); } } goto out; case ID_BOT: { if (RT_G_DEBUG&DEBUG_TREEWALK) { bu_log("fastpath draw ID_BOT %s\n", dp->d_namep); } if (dgcdp->draw_wireframes) { (void)rt_bot_plot(&vhead, &intern, tsp->ts_ttol, tsp->ts_tol, NULL); } else { (void)rt_bot_plot_poly(&vhead, &intern, tsp->ts_ttol, tsp->ts_tol); } } goto out; case ID_BREP: { if (RT_G_DEBUG&DEBUG_TREEWALK) { bu_log("fastpath draw ID_BREP %s\n", dp->d_namep); } if (dgcdp->draw_wireframes) { (void)rt_brep_plot(&vhead, &intern, tsp->ts_ttol, tsp->ts_tol, NULL); } else { (void)rt_brep_plot_poly(&vhead, pathp, &intern, tsp->ts_ttol, tsp->ts_tol, NULL); } } goto out; case ID_COMBINATION: default: break; } rt_db_free_internal(&intern); return 0; out: { struct db_full_path pp; db_full_path_init(&pp); db_dup_full_path(&pp, pathp); /* Successful fastpath drawing of this solid */ db_add_node_to_full_path(&pp, dp); _ged_drawH_part2(0, &vhead, &pp, tsp, dgcdp); db_free_full_path(&pp); } rt_db_free_internal(&intern); dgcdp->fastpath_count++; return -1; /* SKIP THIS REGION */ }
/** * R T _ G E T T R E E _ L E A F * * This routine must be prepared to run in parallel. */ HIDDEN union tree *rt_gettree_leaf(struct db_tree_state *tsp, struct db_full_path *pathp, struct rt_db_internal *ip, genptr_t client_data) /*const*/ /*const*/ { register struct soltab *stp; union tree *curtree; struct directory *dp; register matp_t mat; int i; struct rt_i *rtip; RT_CK_DBTS(tsp); RT_CK_DBI(tsp->ts_dbip); RT_CK_FULL_PATH(pathp); RT_CK_DB_INTERNAL(ip); rtip = tsp->ts_rtip; RT_CK_RTI(rtip); RT_CK_RESOURCE(tsp->ts_resp); dp = DB_FULL_PATH_CUR_DIR(pathp); /* Determine if this matrix is an identity matrix */ if ( !bn_mat_is_equal(tsp->ts_mat, bn_mat_identity, &rtip->rti_tol)) { /* Not identity matrix */ mat = (matp_t)tsp->ts_mat; } else { /* Identity matrix */ mat = (matp_t)0; } /* * Check to see if this exact solid has already been processed. * Match on leaf name and matrix. Note that there is a race here * between having st_id filled in a few lines below (which is * necessary for calling ft_prep), and ft_prep filling in * st_aradius. Fortunately, st_aradius starts out as zero, and * will never go down to -1 unless this soltab structure has * become a dead solid, so by testing against -1 (instead of <= 0, * like before, oops), it isn't a problem. */ stp = rt_find_identical_solid( mat, dp, rtip ); if ( stp->st_id != 0 ) { /* stp is an instance of a pre-existing solid */ if ( stp->st_aradius <= -1 ) { /* It's dead, Jim. st_uses was not incremented. */ return( TREE_NULL ); /* BAD: instance of dead solid */ } goto found_it; } if ( rtip->rti_add_to_new_solids_list ) { bu_ptbl_ins( &rtip->rti_new_solids, (long *)stp ); } stp->st_id = ip->idb_type; stp->st_meth = &rt_functab[ip->idb_type]; if ( mat ) { mat = stp->st_matp; } else { mat = (matp_t)bn_mat_identity; } RT_CK_DB_INTERNAL( ip ); /* init solid's maxima and minima */ VSETALL( stp->st_max, -INFINITY ); VSETALL( stp->st_min, INFINITY ); /* * If the ft_prep routine wants to keep the internal structure, * that is OK, as long as idb_ptr is set to null. Note that the * prep routine may have changed st_id. */ if ( stp->st_meth->ft_prep( stp, ip, rtip ) ) { int hash; /* Error, solid no good */ bu_log("rt_gettree_leaf(%s): prep failure\n", dp->d_namep ); /* Too late to delete soltab entry; mark it as "dead" */ hash = db_dirhash( dp->d_namep ); ACQUIRE_SEMAPHORE_TREE(hash); stp->st_aradius = -1; stp->st_uses--; RELEASE_SEMAPHORE_TREE(hash); return( TREE_NULL ); /* BAD */ } if ( rtip->rti_dont_instance ) { /* * If instanced solid refs are not being compressed, then * memory isn't an issue, and the application (such as * solids_on_ray) probably cares about the full path of this * solid, from root to leaf. So make it available here. * (stp->st_dp->d_uses could be the way to discriminate * references uniquely, if the path isn't enough. To locate * given dp and d_uses, search dp->d_use_hd list. Question * is, where to stash current val of d_uses?) */ db_full_path_init( &stp->st_path ); db_dup_full_path( &stp->st_path, pathp ); } else { /* * If there is more than just a direct reference to this leaf * from it's containing region, copy that below-region path * into st_path. Otherwise, leave st_path's magic number 0. * * XXX nothing depends on this behavior yet, and this whole * XXX 'else' clause might well be deleted. -Mike */ i = pathp->fp_len-1; if ( i > 0 && !(pathp->fp_names[i-1]->d_flags & DIR_REGION) ) { /* Search backwards for region. If no region, use whole path */ for ( --i; i > 0; i-- ) { if ( pathp->fp_names[i-1]->d_flags & DIR_REGION ) break; } if ( i < 0 ) i = 0; db_full_path_init( &stp->st_path ); db_dup_path_tail( &stp->st_path, pathp, i ); } } if (RT_G_DEBUG&DEBUG_TREEWALK && stp->st_path.magic == DB_FULL_PATH_MAGIC) { char *sofar = db_path_to_string(&stp->st_path); bu_log("rt_gettree_leaf() st_path=%s\n", sofar ); bu_free(sofar, "path string"); } if (RT_G_DEBUG&DEBUG_SOLIDS) { struct bu_vls str; bu_log("\n---Primitive %d: %s\n", stp->st_bit, dp->d_namep); bu_vls_init( &str ); /* verbose=1, mm2local=1.0 */ if ( stp->st_meth->ft_describe( &str, ip, 1, 1.0, tsp->ts_resp, tsp->ts_dbip ) < 0 ) { bu_log("rt_gettree_leaf(%s): solid describe failure\n", dp->d_namep ); } bu_log( "%s: %s", dp->d_namep, bu_vls_addr( &str ) ); bu_vls_free( &str ); } found_it: RT_GET_TREE( curtree, tsp->ts_resp ); curtree->magic = RT_TREE_MAGIC; curtree->tr_op = OP_SOLID; curtree->tr_a.tu_stp = stp; /* regionp will be filled in later by rt_tree_region_assign() */ curtree->tr_a.tu_regionp = (struct region *)0; if (RT_G_DEBUG&DEBUG_TREEWALK) { char *sofar = db_path_to_string(pathp); bu_log("rt_gettree_leaf() %s\n", sofar ); bu_free(sofar, "path string"); } return(curtree); }