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;
}
Exemple #6
0
/**
 * 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);
}