Revision: 69024
http://sourceforge.net/p/brlcad/code/69024
Author: starseeker
Date: 2016-10-11 17:54:52 +0000 (Tue, 11 Oct 2016)
Log Message:
-----------
Shift some clearly librt requiring bits into nmg.c
Modified Paths:
--------------
brlcad/trunk/src/librt/primitives/nmg/nmg.c
brlcad/trunk/src/librt/primitives/nmg/nmg_bool.c
Modified: brlcad/trunk/src/librt/primitives/nmg/nmg.c
===================================================================
--- brlcad/trunk/src/librt/primitives/nmg/nmg.c 2016-10-11 17:44:12 UTC (rev
69023)
+++ brlcad/trunk/src/librt/primitives/nmg/nmg.c 2016-10-11 17:54:52 UTC (rev
69024)
@@ -3299,6 +3299,447 @@
filename);
}
+
+/* moved from nmg_bool.c - not sure where it should ultimately end up... */
+
+
+/**
+ * Called from db_walk_tree() each time a tree leaf is encountered.
+ * The primitive solid, in external format, is provided in 'ep', and
+ * the type of that solid (e.g. ID_ELL) is in 'id'. The full tree
+ * state including the accumulated transformation matrix and the
+ * current tolerancing is in 'tsp', and the full path from root to
+ * leaf is in 'pathp'.
+ *
+ * Import the solid, tessellate it into an NMG, stash a pointer to the
+ * tessellation in a new tree structure (union), and return a pointer
+ * to that.
+ *
+ * Usually given as an argument to, and called from db_walk_tree().
+ *
+ * This routine must be prepared to run in parallel.
+ */
+union tree *
+nmg_booltree_leaf_tess(struct db_tree_state *tsp, const struct db_full_path
*pathp, struct rt_db_internal *ip, void *UNUSED(client_data))
+{
+ struct model *m;
+ struct nmgregion *r1 = (struct nmgregion *)NULL;
+ union tree *curtree;
+ struct directory *dp;
+
+ if (!tsp || !pathp || !ip)
+ return TREE_NULL;
+
+ RT_CK_DB_INTERNAL(ip);
+ RT_CK_FULL_PATH(pathp);
+ dp = DB_FULL_PATH_CUR_DIR(pathp);
+ RT_CK_DIR(dp);
+
+ if (!ip->idb_meth || !ip->idb_meth->ft_tessellate) {
+ bu_log("ERROR(%s): tessellation support not available\n", dp->d_namep);
+ return TREE_NULL;
+ }
+
+ NMG_CK_MODEL(*tsp->ts_m);
+ BN_CK_TOL(tsp->ts_tol);
+ RT_CK_TESS_TOL(tsp->ts_ttol);
+ RT_CK_RESOURCE(tsp->ts_resp);
+
+ m = nmg_mm();
+
+ if (ip->idb_meth->ft_tessellate(&r1, m, ip, tsp->ts_ttol, tsp->ts_tol) <
0) {
+ bu_log("ERROR(%s): tessellation failure\n", dp->d_namep);
+ return TREE_NULL;
+ }
+
+ NMG_CK_REGION(r1);
+ if (RTG.NMG_debug & DEBUG_VERIFY) {
+ nmg_vshell(&r1->s_hd, r1);
+ }
+
+ RT_GET_TREE(curtree, tsp->ts_resp);
+ curtree->tr_op = OP_NMG_TESS;
+ curtree->tr_d.td_name = bu_strdup(dp->d_namep);
+ curtree->tr_d.td_r = r1;
+
+ if (RT_G_DEBUG&DEBUG_TREEWALK)
+ bu_log("nmg_booltree_leaf_tess(%s) OK\n", dp->d_namep);
+
+ return curtree;
+}
+
+
+/**
+ * Called from db_walk_tree() each time a tree leaf is encountered.
+ * The primitive solid, in external format, is provided in 'ep', and
+ * the type of that solid (e.g. ID_ELL) is in 'id'. The full tree
+ * state including the accumulated transformation matrix and the
+ * current tolerancing is in 'tsp', and the full path from root to
+ * leaf is in 'pathp'.
+ *
+ * Import the solid, convert it into an NMG using t-NURBS, stash a
+ * pointer in a new tree structure (union), and return a pointer to
+ * that.
+ *
+ * Usually given as an argument to, and called from db_walk_tree().
+ *
+ * This routine must be prepared to run in parallel.
+ */
+union tree *
+nmg_booltree_leaf_tnurb(struct db_tree_state *tsp, const struct db_full_path
*pathp, struct rt_db_internal *ip, void *UNUSED(client_data))
+{
+ struct nmgregion *r1;
+ union tree *curtree;
+ struct directory *dp;
+
+ NMG_CK_MODEL(*tsp->ts_m);
+ BN_CK_TOL(tsp->ts_tol);
+ RT_CK_TESS_TOL(tsp->ts_ttol);
+ RT_CK_DB_INTERNAL(ip);
+ RT_CK_RESOURCE(tsp->ts_resp);
+
+ RT_CK_FULL_PATH(pathp);
+ dp = DB_FULL_PATH_CUR_DIR(pathp);
+ RT_CK_DIR(dp);
+
+ if (ip->idb_meth->ft_tnurb(
+ &r1, *tsp->ts_m, ip, tsp->ts_tol) < 0) {
+ bu_log("nmg_booltree_leaf_tnurb(%s): CSG to t-NURB conversation
failure\n", dp->d_namep);
+ return TREE_NULL;
+ }
+
+ NMG_CK_REGION(r1);
+ if (RTG.NMG_debug & DEBUG_VERIFY) {
+ nmg_vshell(&r1->s_hd, r1);
+ }
+
+ RT_GET_TREE(curtree, tsp->ts_resp);
+ curtree->tr_op = OP_NMG_TESS;
+ curtree->tr_d.td_name = bu_strdup(dp->d_namep);
+ curtree->tr_d.td_r = r1;
+
+ if (RT_G_DEBUG&DEBUG_TREEWALK)
+ bu_log("nmg_booltree_leaf_tnurb(%s) OK\n", dp->d_namep);
+
+ return curtree;
+}
+
+
+/* quell the output of nmg_booltree_evaluate() to bu_log. */
+int nmg_bool_eval_silent=0;
+
+/**
+ * Given a tree of leaf nodes tessellated earlier by
+ * nmg_booltree_leaf_tess(), use recursion to do a depth-first
+ * traversal of the tree, evaluating each pair of boolean operations
+ * and reducing that result to a single nmgregion.
+ *
+ * Usually called from a do_region_end() handler from db_walk_tree().
+ * For an example of several, see mged/dodraw.c.
+ *
+ * Returns an OP_NMG_TESS union tree node, which will contain the
+ * resulting region and its name, as a dynamic string. The caller is
+ * responsible for releasing the string, and the node, by calling
+ * db_free_tree() on the node.
+ *
+ * It is *essential* that the caller call nmg_model_fuse() before
+ * calling this subroutine.
+ *
+ * Returns NULL if there is no geometry to return.
+ *
+ * Typical calls will be of this form:
+ * (void)nmg_model_fuse(m, tol);
+ * curtree = nmg_booltree_evaluate(curtree, tol);
+ */
+union tree *
+nmg_booltree_evaluate(register union tree *tp, struct bu_list *vlfree, const
struct bn_tol *tol, struct resource *resp)
+{
+ union tree *tl;
+ union tree *tr;
+ struct nmgregion *reg;
+ int op = NMG_BOOL_ADD; /* default value */
+ const char *op_str = " u "; /* default value */
+ size_t rem;
+ char *name;
+
+ RT_CK_TREE(tp);
+ BN_CK_TOL(tol);
+ RT_CK_RESOURCE(resp);
+
+ switch (tp->tr_op) {
+ case OP_NOP:
+ return TREE_NULL;
+ case OP_NMG_TESS:
+ /* Hit a tree leaf */
+ if (RTG.NMG_debug & DEBUG_VERIFY) {
+ nmg_vshell(&tp->tr_d.td_r->s_hd, tp->tr_d.td_r);
+ }
+ return tp;
+ case OP_UNION:
+ op = NMG_BOOL_ADD;
+ op_str = " u ";
+ break;
+ case OP_INTERSECT:
+ op = NMG_BOOL_ISECT;
+ op_str = " + ";
+ break;
+ case OP_SUBTRACT:
+ op = NMG_BOOL_SUB;
+ op_str = " - ";
+ break;
+ default:
+ bu_bomb("nmg_booltree_evaluate(): bad op\n");
+ }
+
+ /* Handle a boolean operation node. First get its leaves. */
+ tl = nmg_booltree_evaluate(tp->tr_b.tb_left, vlfree, tol, resp);
+ tr = nmg_booltree_evaluate(tp->tr_b.tb_right, vlfree, tol, resp);
+
+ if (tl) {
+ RT_CK_TREE(tl);
+ if (tl != tp->tr_b.tb_left) {
+ bu_bomb("nmg_booltree_evaluate(): tl != tp->tr_b.tb_left\n");
+ }
+ }
+ if (tr) {
+ RT_CK_TREE(tr);
+ if (tr != tp->tr_b.tb_right) {
+ bu_bomb("nmg_booltree_evaluate(): tr != tp->tr_b.tb_right\n");
+ }
+ }
+
+ if (!tl && !tr) {
+ /* left-r == null && right-r == null */
+ RT_CK_TREE(tp);
+ db_free_tree(tp->tr_b.tb_left, resp);
+ db_free_tree(tp->tr_b.tb_right, resp);
+ tp->tr_op = OP_NOP;
+ return TREE_NULL;
+ }
+
+ if (tl && !tr) {
+ /* left-r != null && right-r == null */
+ RT_CK_TREE(tp);
+ db_free_tree(tp->tr_b.tb_right, resp);
+ if (op == NMG_BOOL_ISECT) {
+ /* OP_INTERSECT '+' */
+ RT_CK_TREE(tp);
+ db_free_tree(tl, resp);
+ tp->tr_op = OP_NOP;
+ return TREE_NULL;
+ } else {
+ /* copy everything from tl to tp no matter which union type
+ * could probably have done a mem-copy
+ */
+ tp->tr_op = tl->tr_op;
+ tp->tr_b.tb_regionp = tl->tr_b.tb_regionp;
+ tp->tr_b.tb_left = tl->tr_b.tb_left;
+ tp->tr_b.tb_right = tl->tr_b.tb_right;
+
+ /* null data from tl so only to free this node */
+ tl->tr_b.tb_regionp = (struct region *)NULL;
+ tl->tr_b.tb_left = TREE_NULL;
+ tl->tr_b.tb_right = TREE_NULL;
+
+ db_free_tree(tl, resp);
+ return tp;
+ }
+ }
+
+ if (!tl && tr) {
+ /* left-r == null && right-r != null */
+ RT_CK_TREE(tp);
+ db_free_tree(tp->tr_b.tb_left, resp);
+ if (op == NMG_BOOL_ADD) {
+ /* OP_UNION 'u' */
+ /* copy everything from tr to tp no matter which union type
+ * could probably have done a mem-copy
+ */
+ tp->tr_op = tr->tr_op;
+ tp->tr_b.tb_regionp = tr->tr_b.tb_regionp;
+ tp->tr_b.tb_left = tr->tr_b.tb_left;
+ tp->tr_b.tb_right = tr->tr_b.tb_right;
+
+ /* null data from tr so only to free this node */
+ tr->tr_b.tb_regionp = (struct region *)NULL;
+ tr->tr_b.tb_left = TREE_NULL;
+ tr->tr_b.tb_right = TREE_NULL;
+
+ db_free_tree(tr, resp);
+ return tp;
+
+ } else if ((op == NMG_BOOL_SUB) || (op == NMG_BOOL_ISECT)) {
+ /* for sub and intersect, if left-hand-side is null, result is null
*/
+ RT_CK_TREE(tp);
+ db_free_tree(tr, resp);
+ tp->tr_op = OP_NOP;
+ return TREE_NULL;
+
+ } else {
+ bu_bomb("nmg_booltree_evaluate(): error, unknown operation\n");
+ }
+ }
+
+ if (tl->tr_op != OP_NMG_TESS) {
+ bu_bomb("nmg_booltree_evaluate(): bad left tree\n");
+ }
+ if (tr->tr_op != OP_NMG_TESS) {
+ bu_bomb("nmg_booltree_evaluate(): bad right tree\n");
+ }
+
+ if (!nmg_bool_eval_silent) {
+ bu_log(" {%s}%s{%s}\n", tl->tr_d.td_name, op_str, tr->tr_d.td_name);
+ }
+
+ NMG_CK_REGION(tr->tr_d.td_r);
+ NMG_CK_REGION(tl->tr_d.td_r);
+
+ if (nmg_ck_closed_region(tr->tr_d.td_r, tol)) {
+ bu_bomb("nmg_booltree_evaluate(): ERROR, non-closed shell (r)\n");
+ }
+ if (nmg_ck_closed_region(tl->tr_d.td_r, tol)) {
+ bu_bomb("nmg_booltree_evaluate(): ERROR, non-closed shell (l)\n");
+ }
+
+ nmg_r_radial_check(tr->tr_d.td_r, vlfree, tol);
+ nmg_r_radial_check(tl->tr_d.td_r, vlfree, tol);
+
+ if (RTG.NMG_debug & DEBUG_BOOL) {
+ bu_log("Before model fuse\nShell A:\n");
+ nmg_pr_s_briefly(BU_LIST_FIRST(shell, &tl->tr_d.td_r->s_hd), "");
+ bu_log("Shell B:\n");
+ nmg_pr_s_briefly(BU_LIST_FIRST(shell, &tr->tr_d.td_r->s_hd), "");
+ }
+
+ /* move operands into the same model */
+ if (tr->tr_d.td_r->m_p != tl->tr_d.td_r->m_p) {
+ nmg_merge_models(tl->tr_d.td_r->m_p, tr->tr_d.td_r->m_p);
+ }
+
+ /* input r1 and r2 are destroyed, output is new region */
+ reg = nmg_do_bool(tl->tr_d.td_r, tr->tr_d.td_r, op, vlfree, tol);
+
+ /* build string of result name */
+ rem = strlen(tl->tr_d.td_name) + 3 + strlen(tr->tr_d.td_name) + 2 + 1;
+ name = (char *)bu_calloc(rem, sizeof(char), "nmg_booltree_evaluate name");
+ snprintf(name, rem, "(%s%s%s)", tl->tr_d.td_name, op_str,
tr->tr_d.td_name);
+
+ /* clean up child tree nodes */
+ tl->tr_d.td_r = (struct nmgregion *)NULL;
+ tr->tr_d.td_r = (struct nmgregion *)NULL;
+ db_free_tree(tl, resp);
+ db_free_tree(tr, resp);
+
+
+ if (reg) {
+ /* convert argument binary node into a result node */
+ NMG_CK_REGION(reg);
+ nmg_r_radial_check(reg, vlfree, tol);
+ tp->tr_op = OP_NMG_TESS;
+ tp->tr_d.td_r = reg;
+ tp->tr_d.td_name = name;
+
+ if (RTG.NMG_debug & DEBUG_VERIFY) {
+ nmg_vshell(®->s_hd, reg);
+ }
+ return tp;
+
+ } else {
+ /* resulting region was null */
+ tp->tr_op = OP_NOP;
+ return TREE_NULL;
+ }
+
+}
+
+
+/**
+ * This is the main application interface to the NMG Boolean
+ * Evaluator.
+ *
+ * This routine has the opportunity to do "once only" operations
+ * before and after the boolean tree is walked.
+ *
+ * Returns -
+ * 0 Boolean went OK. Result region is in tp->tr_d.td_r
+ * !0 Boolean produced null result.
+ *
+ * The caller is responsible for freeing 'tp' in either case,
+ * typically with db_free_tree(tp);
+ */
+int
+nmg_boolean(union tree *tp, struct model *m, struct bu_list *vlfree, const
struct bn_tol *tol, struct resource *resp)
+{
+ union tree *result;
+ int ret;
+
+ RT_CK_TREE(tp);
+ NMG_CK_MODEL(m);
+ BN_CK_TOL(tol);
+ RT_CK_RESOURCE(resp);
+
+ if (RTG.NMG_debug & (DEBUG_BOOL|DEBUG_BASIC)) {
+ bu_log("\n\nnmg_boolean(tp=%p, m=%p) START\n",
+ (void *)tp, (void *)m);
+ }
+
+ /* The nmg_model_fuse function was removed from this point in the
+ * boolean process since not all geometry that is to be processed is
+ * always within the single 'm' nmg model structure passed into this
+ * function. In some cases the geometry resides in multiple nmg model
+ * structures within the 'tp' tree that is passed into this function.
+ * Running nmg_model_fuse is still required but is done later, i.e.
+ * within the nmg_booltree_evaluate function just before the nmg_do_bool
+ * function is called which is when the geometry, in which the boolean
+ * to be performed, is always in a single nmg model structure.
+ */
+
+ /*
+ * Evaluate the nodes of the boolean tree one at a time, until
+ * only a single region remains.
+ */
+ result = nmg_booltree_evaluate(tp, vlfree, tol, resp);
+
+ if (result == TREE_NULL) {
+ bu_log("nmg_boolean(): result of nmg_booltree_evaluate() is NULL\n");
+ rt_pr_tree(tp, 0);
+ ret = 1;
+ goto out;
+ }
+
+ if (result != tp) {
+ bu_bomb("nmg_boolean(): result of nmg_booltree_evaluate() isn't tp\n");
+ }
+
+ RT_CK_TREE(result);
+
+ if (tp->tr_op != OP_NMG_TESS) {
+ bu_log("nmg_boolean(): result of nmg_booltree_evaluate() op !=
OP_NMG_TESS\n");
+ rt_pr_tree(tp, 0);
+ ret = 1;
+ goto out;
+ }
+
+ if (tp->tr_d.td_r == (struct nmgregion *)NULL) {
+ /* Pointers are all OK, but boolean produced null set */
+ ret = 1;
+ goto out;
+ }
+
+ /* move result into correct model */
+ nmg_merge_models(m, tp->tr_d.td_r->m_p);
+ ret = 0;
+
+out:
+ if (RTG.NMG_debug & (DEBUG_BOOL|DEBUG_BASIC)) {
+ bu_log("nmg_boolean(tp=%p, m=%p) END, ret=%d\n\n",
+ (void *)tp, (void *)m, ret);
+ }
+
+ return ret;
+}
+
+
/*
* Local Variables:
* mode: C
Modified: brlcad/trunk/src/librt/primitives/nmg/nmg_bool.c
===================================================================
--- brlcad/trunk/src/librt/primitives/nmg/nmg_bool.c 2016-10-11 17:44:12 UTC
(rev 69023)
+++ brlcad/trunk/src/librt/primitives/nmg/nmg_bool.c 2016-10-11 17:54:52 UTC
(rev 69024)
@@ -1151,445 +1151,6 @@
return r;
}
-
-/* XXX move to ??? Everything from here on down needs to go into another
module */
-
-
-/**
- * Called from db_walk_tree() each time a tree leaf is encountered.
- * The primitive solid, in external format, is provided in 'ep', and
- * the type of that solid (e.g. ID_ELL) is in 'id'. The full tree
- * state including the accumulated transformation matrix and the
- * current tolerancing is in 'tsp', and the full path from root to
- * leaf is in 'pathp'.
- *
- * Import the solid, tessellate it into an NMG, stash a pointer to the
- * tessellation in a new tree structure (union), and return a pointer
- * to that.
- *
- * Usually given as an argument to, and called from db_walk_tree().
- *
- * This routine must be prepared to run in parallel.
- */
-union tree *
-nmg_booltree_leaf_tess(struct db_tree_state *tsp, const struct db_full_path
*pathp, struct rt_db_internal *ip, void *UNUSED(client_data))
-{
- struct model *m;
- struct nmgregion *r1 = (struct nmgregion *)NULL;
- union tree *curtree;
- struct directory *dp;
-
- if (!tsp || !pathp || !ip)
- return TREE_NULL;
-
- RT_CK_DB_INTERNAL(ip);
- RT_CK_FULL_PATH(pathp);
- dp = DB_FULL_PATH_CUR_DIR(pathp);
- RT_CK_DIR(dp);
-
- if (!ip->idb_meth || !ip->idb_meth->ft_tessellate) {
- bu_log("ERROR(%s): tessellation support not available\n", dp->d_namep);
- return TREE_NULL;
- }
-
- NMG_CK_MODEL(*tsp->ts_m);
- BN_CK_TOL(tsp->ts_tol);
- RT_CK_TESS_TOL(tsp->ts_ttol);
- RT_CK_RESOURCE(tsp->ts_resp);
-
- m = nmg_mm();
-
- if (ip->idb_meth->ft_tessellate(&r1, m, ip, tsp->ts_ttol, tsp->ts_tol) <
0) {
- bu_log("ERROR(%s): tessellation failure\n", dp->d_namep);
- return TREE_NULL;
- }
-
- NMG_CK_REGION(r1);
- if (RTG.NMG_debug & DEBUG_VERIFY) {
- nmg_vshell(&r1->s_hd, r1);
- }
-
- RT_GET_TREE(curtree, tsp->ts_resp);
- curtree->tr_op = OP_NMG_TESS;
- curtree->tr_d.td_name = bu_strdup(dp->d_namep);
- curtree->tr_d.td_r = r1;
-
- if (RT_G_DEBUG&DEBUG_TREEWALK)
- bu_log("nmg_booltree_leaf_tess(%s) OK\n", dp->d_namep);
-
- return curtree;
-}
-
-
-/**
- * Called from db_walk_tree() each time a tree leaf is encountered.
- * The primitive solid, in external format, is provided in 'ep', and
- * the type of that solid (e.g. ID_ELL) is in 'id'. The full tree
- * state including the accumulated transformation matrix and the
- * current tolerancing is in 'tsp', and the full path from root to
- * leaf is in 'pathp'.
- *
- * Import the solid, convert it into an NMG using t-NURBS, stash a
- * pointer in a new tree structure (union), and return a pointer to
- * that.
- *
- * Usually given as an argument to, and called from db_walk_tree().
- *
- * This routine must be prepared to run in parallel.
- */
-union tree *
-nmg_booltree_leaf_tnurb(struct db_tree_state *tsp, const struct db_full_path
*pathp, struct rt_db_internal *ip, void *UNUSED(client_data))
-{
- struct nmgregion *r1;
- union tree *curtree;
- struct directory *dp;
-
- NMG_CK_MODEL(*tsp->ts_m);
- BN_CK_TOL(tsp->ts_tol);
- RT_CK_TESS_TOL(tsp->ts_ttol);
- RT_CK_DB_INTERNAL(ip);
- RT_CK_RESOURCE(tsp->ts_resp);
-
- RT_CK_FULL_PATH(pathp);
- dp = DB_FULL_PATH_CUR_DIR(pathp);
- RT_CK_DIR(dp);
-
- if (ip->idb_meth->ft_tnurb(
- &r1, *tsp->ts_m, ip, tsp->ts_tol) < 0) {
- bu_log("nmg_booltree_leaf_tnurb(%s): CSG to t-NURB conversation
failure\n", dp->d_namep);
- return TREE_NULL;
- }
-
- NMG_CK_REGION(r1);
- if (RTG.NMG_debug & DEBUG_VERIFY) {
- nmg_vshell(&r1->s_hd, r1);
- }
-
- RT_GET_TREE(curtree, tsp->ts_resp);
- curtree->tr_op = OP_NMG_TESS;
- curtree->tr_d.td_name = bu_strdup(dp->d_namep);
- curtree->tr_d.td_r = r1;
-
- if (RT_G_DEBUG&DEBUG_TREEWALK)
- bu_log("nmg_booltree_leaf_tnurb(%s) OK\n", dp->d_namep);
-
- return curtree;
-}
-
-
-/* quell the output of nmg_booltree_evaluate() to bu_log. */
-int nmg_bool_eval_silent=0;
-
-/**
- * Given a tree of leaf nodes tessellated earlier by
- * nmg_booltree_leaf_tess(), use recursion to do a depth-first
- * traversal of the tree, evaluating each pair of boolean operations
- * and reducing that result to a single nmgregion.
- *
- * Usually called from a do_region_end() handler from db_walk_tree().
- * For an example of several, see mged/dodraw.c.
- *
- * Returns an OP_NMG_TESS union tree node, which will contain the
- * resulting region and its name, as a dynamic string. The caller is
- * responsible for releasing the string, and the node, by calling
- * db_free_tree() on the node.
- *
- * It is *essential* that the caller call nmg_model_fuse() before
- * calling this subroutine.
- *
- * Returns NULL if there is no geometry to return.
- *
- * Typical calls will be of this form:
- * (void)nmg_model_fuse(m, tol);
- * curtree = nmg_booltree_evaluate(curtree, tol);
- */
-union tree *
-nmg_booltree_evaluate(register union tree *tp, struct bu_list *vlfree, const
struct bn_tol *tol, struct resource *resp)
-{
- union tree *tl;
- union tree *tr;
- struct nmgregion *reg;
- int op = NMG_BOOL_ADD; /* default value */
- const char *op_str = " u "; /* default value */
- size_t rem;
- char *name;
-
- RT_CK_TREE(tp);
- BN_CK_TOL(tol);
- RT_CK_RESOURCE(resp);
-
- switch (tp->tr_op) {
- case OP_NOP:
- return TREE_NULL;
- case OP_NMG_TESS:
- /* Hit a tree leaf */
- if (RTG.NMG_debug & DEBUG_VERIFY) {
- nmg_vshell(&tp->tr_d.td_r->s_hd, tp->tr_d.td_r);
- }
- return tp;
- case OP_UNION:
- op = NMG_BOOL_ADD;
- op_str = " u ";
- break;
- case OP_INTERSECT:
- op = NMG_BOOL_ISECT;
- op_str = " + ";
- break;
- case OP_SUBTRACT:
- op = NMG_BOOL_SUB;
- op_str = " - ";
- break;
- default:
- bu_bomb("nmg_booltree_evaluate(): bad op\n");
- }
-
- /* Handle a boolean operation node. First get its leaves. */
- tl = nmg_booltree_evaluate(tp->tr_b.tb_left, vlfree, tol, resp);
- tr = nmg_booltree_evaluate(tp->tr_b.tb_right, vlfree, tol, resp);
-
- if (tl) {
- RT_CK_TREE(tl);
- if (tl != tp->tr_b.tb_left) {
- bu_bomb("nmg_booltree_evaluate(): tl != tp->tr_b.tb_left\n");
- }
- }
- if (tr) {
- RT_CK_TREE(tr);
- if (tr != tp->tr_b.tb_right) {
- bu_bomb("nmg_booltree_evaluate(): tr != tp->tr_b.tb_right\n");
- }
- }
-
- if (!tl && !tr) {
- /* left-r == null && right-r == null */
- RT_CK_TREE(tp);
- db_free_tree(tp->tr_b.tb_left, resp);
- db_free_tree(tp->tr_b.tb_right, resp);
- tp->tr_op = OP_NOP;
- return TREE_NULL;
- }
-
- if (tl && !tr) {
- /* left-r != null && right-r == null */
- RT_CK_TREE(tp);
- db_free_tree(tp->tr_b.tb_right, resp);
- if (op == NMG_BOOL_ISECT) {
- /* OP_INTERSECT '+' */
- RT_CK_TREE(tp);
- db_free_tree(tl, resp);
- tp->tr_op = OP_NOP;
- return TREE_NULL;
- } else {
- /* copy everything from tl to tp no matter which union type
- * could probably have done a mem-copy
- */
- tp->tr_op = tl->tr_op;
- tp->tr_b.tb_regionp = tl->tr_b.tb_regionp;
- tp->tr_b.tb_left = tl->tr_b.tb_left;
- tp->tr_b.tb_right = tl->tr_b.tb_right;
-
- /* null data from tl so only to free this node */
- tl->tr_b.tb_regionp = (struct region *)NULL;
- tl->tr_b.tb_left = TREE_NULL;
- tl->tr_b.tb_right = TREE_NULL;
-
- db_free_tree(tl, resp);
- return tp;
- }
- }
-
- if (!tl && tr) {
- /* left-r == null && right-r != null */
- RT_CK_TREE(tp);
- db_free_tree(tp->tr_b.tb_left, resp);
- if (op == NMG_BOOL_ADD) {
- /* OP_UNION 'u' */
- /* copy everything from tr to tp no matter which union type
- * could probably have done a mem-copy
- */
- tp->tr_op = tr->tr_op;
- tp->tr_b.tb_regionp = tr->tr_b.tb_regionp;
- tp->tr_b.tb_left = tr->tr_b.tb_left;
- tp->tr_b.tb_right = tr->tr_b.tb_right;
-
- /* null data from tr so only to free this node */
- tr->tr_b.tb_regionp = (struct region *)NULL;
- tr->tr_b.tb_left = TREE_NULL;
- tr->tr_b.tb_right = TREE_NULL;
-
- db_free_tree(tr, resp);
- return tp;
-
- } else if ((op == NMG_BOOL_SUB) || (op == NMG_BOOL_ISECT)) {
- /* for sub and intersect, if left-hand-side is null, result is null
*/
- RT_CK_TREE(tp);
- db_free_tree(tr, resp);
- tp->tr_op = OP_NOP;
- return TREE_NULL;
-
- } else {
- bu_bomb("nmg_booltree_evaluate(): error, unknown operation\n");
- }
- }
-
- if (tl->tr_op != OP_NMG_TESS) {
- bu_bomb("nmg_booltree_evaluate(): bad left tree\n");
- }
- if (tr->tr_op != OP_NMG_TESS) {
- bu_bomb("nmg_booltree_evaluate(): bad right tree\n");
- }
-
- if (!nmg_bool_eval_silent) {
- bu_log(" {%s}%s{%s}\n", tl->tr_d.td_name, op_str, tr->tr_d.td_name);
- }
-
- NMG_CK_REGION(tr->tr_d.td_r);
- NMG_CK_REGION(tl->tr_d.td_r);
-
- if (nmg_ck_closed_region(tr->tr_d.td_r, tol)) {
- bu_bomb("nmg_booltree_evaluate(): ERROR, non-closed shell (r)\n");
- }
- if (nmg_ck_closed_region(tl->tr_d.td_r, tol)) {
- bu_bomb("nmg_booltree_evaluate(): ERROR, non-closed shell (l)\n");
- }
-
- nmg_r_radial_check(tr->tr_d.td_r, vlfree, tol);
- nmg_r_radial_check(tl->tr_d.td_r, vlfree, tol);
-
- if (RTG.NMG_debug & DEBUG_BOOL) {
- bu_log("Before model fuse\nShell A:\n");
- nmg_pr_s_briefly(BU_LIST_FIRST(shell, &tl->tr_d.td_r->s_hd), "");
- bu_log("Shell B:\n");
- nmg_pr_s_briefly(BU_LIST_FIRST(shell, &tr->tr_d.td_r->s_hd), "");
- }
-
- /* move operands into the same model */
- if (tr->tr_d.td_r->m_p != tl->tr_d.td_r->m_p) {
- nmg_merge_models(tl->tr_d.td_r->m_p, tr->tr_d.td_r->m_p);
- }
-
- /* input r1 and r2 are destroyed, output is new region */
- reg = nmg_do_bool(tl->tr_d.td_r, tr->tr_d.td_r, op, vlfree, tol);
-
- /* build string of result name */
- rem = strlen(tl->tr_d.td_name) + 3 + strlen(tr->tr_d.td_name) + 2 + 1;
- name = (char *)bu_calloc(rem, sizeof(char), "nmg_booltree_evaluate name");
- snprintf(name, rem, "(%s%s%s)", tl->tr_d.td_name, op_str,
tr->tr_d.td_name);
-
- /* clean up child tree nodes */
- tl->tr_d.td_r = (struct nmgregion *)NULL;
- tr->tr_d.td_r = (struct nmgregion *)NULL;
- db_free_tree(tl, resp);
- db_free_tree(tr, resp);
-
-
- if (reg) {
- /* convert argument binary node into a result node */
- NMG_CK_REGION(reg);
- nmg_r_radial_check(reg, vlfree, tol);
- tp->tr_op = OP_NMG_TESS;
- tp->tr_d.td_r = reg;
- tp->tr_d.td_name = name;
-
- if (RTG.NMG_debug & DEBUG_VERIFY) {
- nmg_vshell(®->s_hd, reg);
- }
- return tp;
-
- } else {
- /* resulting region was null */
- tp->tr_op = OP_NOP;
- return TREE_NULL;
- }
-
-}
-
-
-/**
- * This is the main application interface to the NMG Boolean
- * Evaluator.
- *
- * This routine has the opportunity to do "once only" operations
- * before and after the boolean tree is walked.
- *
- * Returns -
- * 0 Boolean went OK. Result region is in tp->tr_d.td_r
- * !0 Boolean produced null result.
- *
- * The caller is responsible for freeing 'tp' in either case,
- * typically with db_free_tree(tp);
- */
-int
-nmg_boolean(union tree *tp, struct model *m, struct bu_list *vlfree, const
struct bn_tol *tol, struct resource *resp)
-{
- union tree *result;
- int ret;
-
- RT_CK_TREE(tp);
- NMG_CK_MODEL(m);
- BN_CK_TOL(tol);
- RT_CK_RESOURCE(resp);
-
- if (RTG.NMG_debug & (DEBUG_BOOL|DEBUG_BASIC)) {
- bu_log("\n\nnmg_boolean(tp=%p, m=%p) START\n",
- (void *)tp, (void *)m);
- }
-
- /* The nmg_model_fuse function was removed from this point in the
- * boolean process since not all geometry that is to be processed is
- * always within the single 'm' nmg model structure passed into this
- * function. In some cases the geometry resides in multiple nmg model
- * structures within the 'tp' tree that is passed into this function.
- * Running nmg_model_fuse is still required but is done later, i.e.
- * within the nmg_booltree_evaluate function just before the nmg_do_bool
- * function is called which is when the geometry, in which the boolean
- * to be performed, is always in a single nmg model structure.
- */
-
- /*
- * Evaluate the nodes of the boolean tree one at a time, until
- * only a single region remains.
- */
- result = nmg_booltree_evaluate(tp, vlfree, tol, resp);
-
- if (result == TREE_NULL) {
- bu_log("nmg_boolean(): result of nmg_booltree_evaluate() is NULL\n");
- rt_pr_tree(tp, 0);
- ret = 1;
- goto out;
- }
-
- if (result != tp) {
- bu_bomb("nmg_boolean(): result of nmg_booltree_evaluate() isn't tp\n");
- }
-
- RT_CK_TREE(result);
-
- if (tp->tr_op != OP_NMG_TESS) {
- bu_log("nmg_boolean(): result of nmg_booltree_evaluate() op !=
OP_NMG_TESS\n");
- rt_pr_tree(tp, 0);
- ret = 1;
- goto out;
- }
-
- if (tp->tr_d.td_r == (struct nmgregion *)NULL) {
- /* Pointers are all OK, but boolean produced null set */
- ret = 1;
- goto out;
- }
-
- /* move result into correct model */
- nmg_merge_models(m, tp->tr_d.td_r->m_p);
- ret = 0;
-
-out:
- if (RTG.NMG_debug & (DEBUG_BOOL|DEBUG_BASIC)) {
- bu_log("nmg_boolean(tp=%p, m=%p) END, ret=%d\n\n",
- (void *)tp, (void *)m, ret);
- }
-
- return ret;
-}
/** @} */
/*
This was sent by the SourceForge.net collaborative development platform, the
world's largest Open Source development site.
------------------------------------------------------------------------------
Check out the vibrant tech community on one of the world's most
engaging tech sites, SlashDot.org! http://sdm.link/slashdot
_______________________________________________
BRL-CAD Source Commits mailing list
[email protected]
https://lists.sourceforge.net/lists/listinfo/brlcad-commits