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(&reg->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(&reg->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

Reply via email to