Revision: 46518 http://brlcad.svn.sourceforge.net/brlcad/?rev=46518&view=rev Author: abhi2011 Date: 2011-09-01 00:33:22 +0000 (Thu, 01 Sep 2011) Log Message: ----------- Modified the BB function to get the BB for groups, combs and prims through tree traversal
Modified Paths: -------------- brlcad/trunk/src/librt/bbox.c Modified: brlcad/trunk/src/librt/bbox.c =================================================================== --- brlcad/trunk/src/librt/bbox.c 2011-08-31 23:19:21 UTC (rev 46517) +++ brlcad/trunk/src/librt/bbox.c 2011-09-01 00:33:22 UTC (rev 46518) @@ -28,6 +28,7 @@ #include "common.h" +#include <string.h> #include "bu.h" #include "vmath.h" #include "raytrace.h" @@ -283,167 +284,261 @@ /** - * Supporting function for R T _ B O U N D _ I N T E R N A L + * R T _ T R A V E R S E _ T R E E * - * Called when a combination is detected during db_functree() tree walk + * Traverse the passed tree using rt_db_internals to show the way + * This function supports rt_bound_internal and is internal to librt * * Returns - - * 0 success - * -1 failure - * + * 0 success + * -1 failure (tree_min and tree_max may have been altered) */ -void -comb_func(struct db_i *dbip, - struct directory *dp, - genptr_t ptr) +int +rt_traverse_tree(struct rt_i *rtip, const union tree *tp, fastf_t *tree_min, fastf_t *tree_max) { - struct rt_db_internal *intern = NULL; + vect_t r_min, r_max; /* rpp for right side of tree */ - bu_log("rt_bound_internal: comb_func called\n"); + RT_CK_TREE(tp); - if (rt_db_get_internal(intern, dp, dbip, ptr, &rt_uniresource) < 0){ - bu_log("rt_bound_internal: comb_func : rt_db_get_internal('%s') failed\n", dp->d_namep); - } - -} + switch (tp->tr_op) { + case OP_SOLID: + { + const struct soltab *stp; -/** - * Supporting function for R T _ B O U N D _ I N T E R N A L - * - * Called when a leaf is detected during db_functree() tree walk - * - * Returns - - * 0 success - * -1 failure - * - */ -void -leaf_func(struct db_i *dbip, - struct directory *dp, - genptr_t ptr) -{ - struct rt_db_internal *intern = NULL; + stp = tp->tr_a.tu_stp; + RT_CK_SOLTAB(stp); + if (stp->st_aradius <= 0) { + bu_log("rt_traverse_tree: encountered dead solid '%s'\n", + stp->st_dp->d_namep); + return -1; /* ERROR */ + } - bu_log("rt_bound_internal: leaf_func called\n"); + if (stp->st_aradius >= INFINITY) { + VSETALL(tree_min, -INFINITY); + VSETALL(tree_max, INFINITY); + return 0; + } + VMOVE(tree_min, stp->st_min); + VMOVE(tree_max, stp->st_max); + return 0; + } - if (rt_db_get_internal(intern, dp, dbip, ptr, &rt_uniresource) < 0){ - bu_log("rt_bound_internal: leaf_func : rt_db_get_internal('%s') failed\n", dp->d_namep); - } + default: + bu_log("rt_traverse_tree(x%x): unknown op=x%x\n", tp, (unsigned int)(tp->tr_op)); + return -1; + + case OP_XOR: + case OP_UNION: + /* BINARY type -- expand to contain both */ + if (rt_traverse_tree(rtip, tp->tr_b.tb_left, tree_min, tree_max) < 0 || + rt_traverse_tree(rtip, tp->tr_b.tb_right, r_min, r_max) < 0) + return -1; + VMIN(tree_min, r_min); + VMAX(tree_max, r_max); + break; + case OP_INTERSECT: + /* BINARY type -- find common area only */ + if (rt_traverse_tree(rtip, tp->tr_b.tb_left, tree_min, tree_max) < 0 || + rt_traverse_tree(rtip, tp->tr_b.tb_right, r_min, r_max) < 0) + return -1; + /* min = largest min, max = smallest max */ + VMAX(tree_min, r_min); + VMIN(tree_max, r_max); + break; + case OP_SUBTRACT: + /* BINARY type -- just use left tree */ + if (rt_traverse_tree(rtip, tp->tr_b.tb_left, tree_min, tree_max) < 0 || + rt_traverse_tree(rtip, tp->tr_b.tb_right, r_min, r_max) < 0) + return -1; + /* Discard right rpp */ + break; + + /* This case is especially for handling rt_db_internal formats which generally contain a "unloaded" + * tree with tp->tr_op = OP_DB_LEAF + */ + case OP_DB_LEAF: + { + if(rtip == NULL){ + bu_log("rt_traverse_tree: A valid rtip was not passed for calculating bounds of '%s'\n", + tp->tr_l.tl_name); + return -1; + } + + /* Good to go */ + const struct soltab *stp; + + /* Attempt to get a solid pointer, will fail for combs */ + stp = rt_find_solid(rtip, tp->tr_l.tl_name); + if(stp == NULL){ + + /* It was a comb! get an internal format and repeat the whole thing that got us here + * in the 1st place + */ + struct rt_db_internal intern; + struct directory *dp; + struct rt_comb_internal *combp; + + /* Get the directory pointer */ + if ((dp=db_lookup(rtip->rti_dbip, tp->tr_l.tl_name, LOOKUP_QUIET)) == RT_DIR_NULL) { + bu_log("rt_traverse_tree: db_lookup(%s) failed", tp->tr_l.tl_name); + return -1; + } + + /* Why does recursion work with the internal format ? + * The internal format does have the boolean op for a comb in the tr_a.tu_op field + * in the root node, even though it has no prims at the leaves. + * So recursive calls to load the prim further down the tree, will return the correct bb + * as we are going through the proper switch case in each step down the tree + */ + if ( !rt_db_lookup_internal(rtip->rti_dbip, tp->tr_l.tl_name, &dp, &intern, LOOKUP_NOISY, + &rt_uniresource)){ + bu_log("rt_traverse_tree: rt_db_lookup_internal(%s) failed to get the internal form", + tp->tr_l.tl_name); + return -1; + } + + /* The passed rt_db_internal should be a comb, prepare a rt_comb_internal */ + if(intern.idb_minor_type == ID_COMBINATION){ + combp = (struct rt_comb_internal *)intern.idb_ptr; + } + else{ /* if its not a comb, then something else is cooking */ + bu_log("rt_traverse_tree: WARNING : rt_db_lookup_internal(%s) got the internal form of a \ + primitive when it should not, the bounds may not be correct", tp->tr_l.tl_name); + return -1; + } + + RT_CK_COMB(combp); + /* further down the rabbit hole */ + if (rt_traverse_tree(rtip, combp->tree, tree_min, tree_max)) { + bu_log("rt_traverse_tree: rt_bound_tree() failed\n"); + return -1; + } + } + else{ + /* Got a solid pointer, get bounds and return */ + RT_CK_SOLTAB(stp); + if (stp->st_aradius <= 0) { + bu_log("rt_traverse_tree: encountered dead solid '%s'\n", + stp->st_dp->d_namep); + return -1; /* ERROR */ + } + + if (stp->st_aradius >= INFINITY) { + VSETALL(tree_min, -INFINITY); + VSETALL(tree_max, INFINITY); + return 0; + } + + VMOVE(tree_min, stp->st_min); + VMOVE(tree_max, stp->st_max); + } + + return 0; + } + + case OP_NOP: + /* Implies that this tree has nothing in it */ + break; + } + return 0; } - + + + /** * R T _ B O U N D _ I N T E R N A L * * Calculate the bounding RPP of the internal format passed in 'ip'. * The bounding RPP is returned in rpp_min and rpp_max in mm + * FIXME: This function needs to be modified to eliminate the rt_gettree() call and the related + * parameters. In that case calling code needs to call another function before calling this function + * That function must create a union tree with tr_a.tu_op=OP_SOLID. It can look as follows : + * union tree * rt_comb_tree(const struct db_i *dbip, const struct rt_db_internal *ip). The tree is set + * in the struct rt_db_internal * ip argument. + * Once a suitable tree is set in the ip, then this function can be called with the struct rt_db_internal * + * to return the BB properly without getting stuck during tree traversal in rt_bound_tree() * * Returns - * 0 success - * -1 failure - * -2 a region/comb was passed so model bounds are 0(will be fixed soon) + * -1 failure, the model bounds could not be got + * */ int -rt_bound_internal(struct rt_db_internal *ip, point_t rpp_min, point_t rpp_max) +rt_bound_internal(struct db_i *dbip, struct directory *dp, + point_t rpp_min, point_t rpp_max) { - struct db_i *dbip; - struct directory *dp = (struct directory *)NULL; struct rt_i *rtip; - struct rt_comb_internal comb; - struct rt_comb_internal *combp = &comb; + struct rt_db_internal intern; + struct rt_comb_internal *combp; vect_t tree_min, tree_max; - - RT_CK_DB_INTERNAL(ip); - - /* Create an empty db_i */ - dbip = db_open_inmem(); - - RT_CK_DBI(dbip); - RT_CK_WDB(dbip->dbi_wdbp); - - /* Insert the passed struct rt_db_internal into the db_i, use a dummy name */ - if (wdb_put_internal(dbip->dbi_wdbp, "dummy", ip, 1.0) < 0) { - bu_log("rt_bound_internal: wdb_put_internal() failed\n"); - db_close(dbip); - return -1; - } - - /* The rt_db_internal pointed to by ip is(annoyingly!) freed by wdb_put_internal(), so look it up */ - dp = db_lookup(dbip, "dummy", LOOKUP_NOISY); - if (!dp) { - bu_log("rt_bound_internal: db_lookup('dummy') failed\n"); - db_close(dbip); - return -1; - } - - /* Now get back the rt_db_internal representation of the user passed object */ - if (rt_db_get_internal(ip, dp, dbip, bn_mat_identity, &rt_uniresource) < 0) { - bu_log("rt_bound_internal: rt_db_get_internal('dummy') failed\n"); - db_close(dbip); - return -1; - } - - /* Get a new rtip for the dbip */ - rtip = rt_new_rti(dbip); - + union tree *tp; + /* Initialize RPP bounds */ - VSETALL(rpp_min, MAX_FASTF); - VREVERSE(rpp_max, rpp_min); - - /* Call rt_gettree() to get the bounds, this is sufficient for primitives : may not be required soon */ - if (rt_gettree(rtip, "dummy") < 0){ - bu_log("rt_bound_internal: rt_gettree('dummy') failed\n"); - goto cleanup; - return -1; - } - - /* For combinations, walk the tree once adding leaves and combinations to the dbip as detected */ - db_functree(dbip, dp, comb_func, leaf_func, &rt_uniresource, NULL); + VSETALL(rpp_min, MAX_FASTF); + VREVERSE(rpp_max, rpp_min); - - /* If passed rt_db_internal is a combination(a group or a region) then further calls needed */ - if(ip->idb_minor_type == ID_COMBINATION){ - combp = (struct rt_comb_internal *)ip->idb_ptr; - } - else{ - VMOVE(rpp_min, rtip->mdl_min); /* temporary, till db_functree() works */ - VMOVE(rpp_max, rtip->mdl_max); - goto cleanup; - return 0; - - /* A primitive was passed, construct a struct rt_comb_internal with a single leaf node */ - /*RT_COMB_INTERNAL_INIT(combp); - union tree *tp; - RT_GET_TREE(tp, &rt_uniresource); - tp->tr_op = OP_DB_LEAF; - tp->tr_l.tl_name = bu_strdup(dp->d_namep); - combp->tree = tp;*/ - } - - RT_CK_COMB(combp); - if (rt_bound_tree(combp->tree, tree_min, tree_max)) { - bu_log("rt_bound_internal: rt_bound_tree('region') failed\n"); - goto cleanup; - return -1; - } - + if ((rtip=rt_new_rti(dbip)) == RTI_NULL) { + bu_log("rt_bound_internal: rt_new_rti() failure while getting bb for %s\n", dp->d_namep); + return -1; + } + + /* Call rt_gettree() to get the bounds for primitives, else soltab ptr is null */ + if (rt_gettree(rtip, dp->d_namep) < 0){ + bu_log("rt_bound_internal: rt_gettree('%s') failed\n", dp->d_namep); + rt_free_rti(rtip); + return -1; + } + + + if ( !rt_db_lookup_internal(dbip, dp->d_namep, &dp, &intern, LOOKUP_NOISY, &rt_uniresource)){ + bu_exit(1,"rt_bound_internal: rt_db_lookup_internal(%s) failed to get the internal form", dp->d_namep); + rt_free_rti(rtip); + return -1; + } + + /* If passed rt_db_internal is a combination(a group or a region) then further calls needed */ + if(intern.idb_minor_type == ID_COMBINATION){ + combp = (struct rt_comb_internal *)intern.idb_ptr; + } + else{ + /* A primitive was passed, construct a struct rt_comb_internal with a single leaf node */ + BU_GETSTRUCT(combp, rt_comb_internal); + RT_COMB_INTERNAL_INIT(combp); + combp->region_flag = 0; + + RT_GET_TREE(tp, &rt_uniresource); + RT_TREE_INIT(tp); + tp->tr_l.tl_op = OP_SOLID; + tp->tr_l.tl_name = "dummy"; + tp->tr_l.tl_mat = (matp_t)NULL; + tp->tr_a.tu_stp = rt_find_solid(rtip, dp->d_namep); + combp->tree = tp; + } + + RT_CK_COMB(combp); + if (rt_traverse_tree(rtip, combp->tree, tree_min, tree_max)) { + bu_log("rt_bound_internal: rt_bound_tree() failed\n"); + rt_free_rti(rtip); + return -1; + } + + VMOVE(rpp_min, tree_min); VMOVE(rpp_max, tree_max); - + /* Check if the model bounds look correct e.g. if they are all 0, then its not correct */ - if( (abs(rpp_min[0]) == 0 || rpp_min[0] <= -INFINITY || rpp_min[0] >= INFINITY) && - (abs(rpp_min[1]) == 0 || rpp_min[1] <= -INFINITY || rpp_min[1] >= INFINITY) && - (abs(rpp_min[2]) == 0 || rpp_min[2] <= -INFINITY || rpp_min[2] >= INFINITY) && - (abs(rpp_max[0]) == 0 || rpp_max[0] <= -INFINITY || rpp_max[0] >= INFINITY) && - (abs(rpp_max[1]) == 0 || rpp_max[1] <= -INFINITY || rpp_max[1] >= INFINITY) && - (abs(rpp_max[2]) == 0 || rpp_max[2] <= -INFINITY || rpp_max[2] >= INFINITY)){ + if( (NEAR_ZERO(rpp_min[0], SMALL_FASTF) || rpp_min[0] <= -INFINITY || rpp_min[0] >= INFINITY) && + (NEAR_ZERO(rpp_min[1], SMALL_FASTF) || rpp_min[1] <= -INFINITY || rpp_min[1] >= INFINITY) && + (NEAR_ZERO(rpp_min[2], SMALL_FASTF) || rpp_min[2] <= -INFINITY || rpp_min[2] >= INFINITY) && + (NEAR_ZERO(rpp_max[0], SMALL_FASTF) || rpp_max[0] <= -INFINITY || rpp_max[0] >= INFINITY) && + (NEAR_ZERO(rpp_max[1], SMALL_FASTF) || rpp_max[1] <= -INFINITY || rpp_max[1] >= INFINITY) && + (NEAR_ZERO(rpp_max[2], SMALL_FASTF) || rpp_max[2] <= -INFINITY || rpp_max[2] >= INFINITY) + ){ bu_log("rt_bound_internal: Warning : The returned bounds of the model may not be correct\n"); - } - - cleanup: + } + rt_free_rti(rtip); - db_close(dbip); - return 0; } This was sent by the SourceForge.net collaborative development platform, the world's largest Open Source development site. ------------------------------------------------------------------------------ Special Offer -- Download ArcSight Logger for FREE! Finally, a world-class log management solution at an even better price-free! And you'll get a free "Love Thy Logs" t-shirt when you download Logger. Secure your free ArcSight Logger TODAY! http://p.sf.net/sfu/arcsisghtdev2dev _______________________________________________ BRL-CAD Source Commits mailing list brlcad-commits@lists.sourceforge.net https://lists.sourceforge.net/lists/listinfo/brlcad-commits