static union tree * facetize_region_end(struct db_tree_state *tsp, const struct db_full_path *pathp, union tree *curtree, void *client_data) { struct bu_list vhead; union tree **facetize_tree; if (tsp) RT_CK_DBTS(tsp); if (pathp) RT_CK_FULL_PATH(pathp); facetize_tree = (union tree **)client_data; BU_LIST_INIT(&vhead); if (curtree->tr_op == OP_NOP) return curtree; if (*facetize_tree) { union tree *tr; BU_ALLOC(tr, union tree); RT_TREE_INIT(tr); tr->tr_op = OP_UNION; tr->tr_b.tb_regionp = REGION_NULL; tr->tr_b.tb_left = *facetize_tree; tr->tr_b.tb_right = curtree; *facetize_tree = tr; } else { *facetize_tree = curtree; } /* Tree has been saved, and will be freed later */ return TREE_NULL; }
static union tree * wireframe_region_end(struct db_tree_state *tsp, const struct db_full_path *pathp, union tree *curtree, void *UNUSED(client_data)) { if (tsp) RT_CK_DBTS(tsp); if (pathp) RT_CK_FULL_PATH(pathp); if (curtree) RT_CK_TREE(curtree); return curtree; }
/** * @brief This is called when all sub-elements of a region have been processed by leaf_func. * * @param tsp tree state * @param pathp db path * @param curtree current tree * * @return TREE_NULL if data in curtree was "stolen", otherwise db_walk_tree will * clean up the data in the union tree * that is returned * * If it wants to retain the data in curtree it can by returning TREE_NULL. Otherwise * db_walk_tree will clean up the data in the union tree * that is returned. * */ union tree * region_end (struct db_tree_state *tsp, const struct db_full_path *pathp, union tree *curtree, void *UNUSED(client_data)) { char *name; RT_CK_DBTS(tsp); name = db_path_to_string(pathp); bu_log("region_end %s\n", name); bu_free(name, "region_end name"); return curtree; }
/** * @brief This routine is called when a region is first encountered in the * hierarchy when processing a tree * * @param tsp tree state (for parsing the tree) * @param pathp A listing of all the nodes traversed to get to this node in the database * @param combp the combination record for this region */ int region_start(struct db_tree_state *tsp, const struct db_full_path *pathp, const struct rt_comb_internal *combp, void *client_data) { char *name; struct directory *dp; struct bu_vls str = BU_VLS_INIT_ZERO; struct user_data *your_stuff = (struct user_data *)client_data; RT_CK_DBTS(tsp); name = db_path_to_string(pathp); bu_log("region_start %s\n", name); bu_free(name, "reg_start name"); bu_log("data = %ld\n", your_stuff->data); rt_pr_tol(&your_stuff->tol); dp = DB_FULL_PATH_CUR_DIR(pathp); /* here is where the conversion should be done */ if (combp->region_flag) printf("Write this region (name=%s) as a part in your format:\n", dp->d_namep); else printf("Write this combination (name=%s) as an assembly in your format:\n", dp->d_namep); describe_tree(combp->tree, &str); printf("\t%s\n\n", bu_vls_addr(&str)); bu_vls_free(&str); return 0; }
/* This routine is called by the tree walker (db_walk_tree) * for every primitive encountered in the trees specified on the command line */ union tree * primitive_func(struct db_tree_state *tsp, const struct db_full_path *pathp, struct rt_db_internal *ip, void *UNUSED(client_data)) { struct directory *dp; char *name; dp = DB_FULL_PATH_CUR_DIR(pathp); RT_CK_DBTS(tsp); name = db_path_to_string(pathp); bu_log("leaf_func %s\n", name); bu_free(name, "region_end name"); /* handle each type of primitive (see h/rtgeom.h) */ if (ip->idb_major_type == DB5_MAJORTYPE_BRLCAD) { switch (ip->idb_type) { /* most commonly used primitives */ case ID_TOR: /* torus */ { struct rt_tor_internal *tor = (struct rt_tor_internal *)ip->idb_ptr; printf("Write this torus (name=%s) in your format:\n", dp->d_namep); printf("\tV=(%g %g %g)\n", V3ARGS(tor->v)); printf("\tnormal=(%g %g %g)\n", V3ARGS(tor->h)); printf("\tradius1 = %g\n", tor->r_a); printf("\tradius2 = %g\n", tor->r_h); break; } case ID_TGC: /* truncated general cone frustum */ case ID_REC: /* right elliptical cylinder */ { /* This primitive includes circular cross-section * cones and cylinders */ struct rt_tgc_internal *tgc = (struct rt_tgc_internal *)ip->idb_ptr; printf("Write this TGC (name=%s) in your format:\n", dp->d_namep); printf("\tV=(%g %g %g)\n", V3ARGS(tgc->v)); printf("\tH=(%g %g %g)\n", V3ARGS(tgc->h)); printf("\tA=(%g %g %g)\n", V3ARGS(tgc->a)); printf("\tB=(%g %g %g)\n", V3ARGS(tgc->b)); printf("\tC=(%g %g %g)\n", V3ARGS(tgc->c)); printf("\tD=(%g %g %g)\n", V3ARGS(tgc->d)); break; } case ID_ELL: case ID_SPH: { /* spheres and ellipsoids */ struct rt_ell_internal *ell = (struct rt_ell_internal *)ip->idb_ptr; printf("Write this ellipsoid (name=%s) in your format:\n", dp->d_namep); printf("\tV=(%g %g %g)\n", V3ARGS(ell->v)); printf("\tA=(%g %g %g)\n", V3ARGS(ell->a)); printf("\tB=(%g %g %g)\n", V3ARGS(ell->b)); printf("\tC=(%g %g %g)\n", V3ARGS(ell->c)); break; } case ID_ARB8: /* convex primitive with from four to six faces */ { int i; /* this primitive may have degenerate faces * faces are: 0123, 7654, 0347, 1562, 0451, 3267 * (points listed above in counter-clockwise order) */ struct rt_arb_internal *arb = (struct rt_arb_internal *)ip->idb_ptr; printf("Write this ARB (name=%s) in your format:\n", dp->d_namep); for (i=0; i<8; i++) printf("\tpoint #%d: (%g %g %g)\n", i, V3ARGS(arb->pt[i])); break; } /* other primitives, left as an exercise to the reader */ case ID_BOT: /* Bag O' Triangles */ case ID_ARS: /* series of curves * each with the same number of points */ case ID_HALF: /* half universe defined by a plane */ case ID_POLY: /* polygons (up to 5 vertices per) */ case ID_BSPLINE: /* NURB surfaces */ case ID_NMG: /* N-manifold geometry */ case ID_ARBN: case ID_DSP: /* Displacement map (terrain primitive) */ /* the DSP primitive may reference an external file or binunif object */ case ID_HF: /* height field (terrain primitive) */ /* the HF primitive references an external file */ case ID_EBM: /* extruded bit-map */ /* the EBM primitive references an external file */ case ID_VOL: /* the VOL primitive references an external file */ case ID_PIPE: case ID_PARTICLE: case ID_RPC: case ID_RHC: case ID_EPA: case ID_EHY: case ID_ETO: case ID_GRIP: case ID_SKETCH: case ID_EXTRUDE: /* note that an extrusion references a sketch, make sure you convert * the sketch also */ default: bu_log("Primitive %s is an unsupported or unrecognized type (%d)\n", dp->d_namep, ip->idb_type); break; } } else { switch (ip->idb_major_type) { case DB5_MAJORTYPE_BINARY_UNIF: { /* not actually a primitive, just a block of storage for data * a uniform array of chars, ints, floats, doubles, ... */ struct rt_binunif_internal *bin = (struct rt_binunif_internal *)ip->idb_ptr; if (bin) printf("Found a binary object (%s)\n\n", dp->d_namep); break; } default: bu_log("Major type of %s is unrecognized type (%d)\n", dp->d_namep, ip->idb_major_type); break; } } return (union tree *) NULL; }
/** * 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); }