Revision: 78061
          http://sourceforge.net/p/brlcad/code/78061
Author:   starseeker
Date:     2021-01-11 19:22:04 +0000 (Mon, 11 Jan 2021)
Log Message:
-----------
Checkpoint.  Slowly working through the conceptual implications of various 
forms of push.

Modified Paths:
--------------
    brlcad/trunk/src/libged/npush/npush.cpp

Modified: brlcad/trunk/src/libged/npush/npush.cpp
===================================================================
--- brlcad/trunk/src/libged/npush/npush.cpp     2021-01-08 19:08:14 UTC (rev 
78060)
+++ brlcad/trunk/src/libged/npush/npush.cpp     2021-01-11 19:22:04 UTC (rev 
78061)
@@ -33,6 +33,46 @@
 
 #include "../ged_private.h"
 
+/* When it comes to push operations, the notion of what constitutes a unique
+ * instance is defined as the combination of the object and its associated
+ * parent matrix. Because the dp may be used under multiple matrices, for some
+ * push operations it will be necessary to generate a new unique name to refer
+ * to instances - we store those names with the instances for convenience. */
+class dp_i {
+    public:
+       struct directory *dp;
+       mat_t mat;
+       std::string iname;
+       const struct bn_tol *ts_tol;
+       bool push_obj = true;
+
+       bool operator<(const dp_i &o) const {
+           if (dp < o.dp) return true;
+           if (o.dp < dp) return false;
+           /* If the dp doesn't tell us, check the matrix. */
+           if (!bn_mat_is_equal(mat, o.mat, ts_tol)) {
+               for (int i = 0; i < 16; i++) {
+                   if (mat[i] < o.mat[i]) {
+                       return true;
+                   }
+               }
+           }
+           return false;
+       }
+};
+
+/* Container to hold information during tree walk.  To generate names (or
+ * recognize when a push would create a conflict) we keep track of how many
+ * times we have encountered each dp during processing. */
+struct push_state {
+    bool survey = false;
+    std::set<std::string> target_objs;
+    std::set<dp_i> s_i;
+    std::map<struct directory *, int> s_c;
+    int verbosity = 0;
+    const struct bn_tol *tol;
+};
+
 static void
 push_walk(struct db_i *dbip,
            struct directory *dp,
@@ -54,6 +94,7 @@
                    void *client_data)
 {
     struct directory *dp;
+    struct push_state *s = (struct push_state *)client_data;
     mat_t om, nm;
 
     if (!tp)
@@ -68,9 +109,18 @@
     switch (tp->tr_op) {
 
        case OP_DB_LEAF:
+
            if ((dp=db_lookup(dbip, tp->tr_l.tl_name, LOOKUP_NOISY)) == 
RT_DIR_NULL)
                return;
 
+           if (s->survey) {
+               // In a survey, if a leaf is one of the originally specified
+               // objects, we're done - below here push logic is active.
+               if (s->target_objs.find(std::string(dp->d_namep)) != 
s->target_objs.end()) {
+                   return;
+               }
+           }
+
            /* Update current matrix state to reflect the new branch of
             * the tree we are about to go down. */
            MAT_COPY(om, *curr_mat);
@@ -150,43 +200,6 @@
 
 
 
-/* When it comes to push operations, the notion of what constitutes a unique
- * instance is defined as the combination of the object and its associated
- * parent matrix. Because the dp may be used under multiple matrices, for some
- * push operations it will be necessary to generate a new unique name to refer
- * to instances - we store those names with the instances for convenience. */
-class dp_i {
-    public:
-       struct directory *dp;
-       mat_t mat;
-       std::string iname;
-       const struct bn_tol *ts_tol;
-
-       bool operator<(const dp_i &o) const {
-           if (dp < o.dp) return true;
-           if (o.dp < dp) return false;
-           /* If the dp doesn't tell us, check the matrix. */
-           if (!bn_mat_is_equal(mat, o.mat, ts_tol)) {
-               for (int i = 0; i < 16; i++) {
-                   if (mat[i] < o.mat[i]) {
-                       return true;
-                   }
-               }
-           }
-           return false;
-       }
-};
-
-/* Container to hold information during tree walk.  To generate names (or
- * recognize when a push would create a conflict) we keep track of how many
- * times we have encountered each dp during processing. */
-struct push_state {
-    std::set<dp_i> s_i;
-    std::map<struct directory *, int> s_c;
-    int verbosity = 0;
-    const struct bn_tol *tol;
-};
-
 static void
 visit_comb_memb(struct db_i *dbip, struct rt_comb_internal *UNUSED(comb), 
union tree *comb_leaf, void *data, void *cm, void *UNUSED(u3), void *UNUSED(u4))
 {
@@ -199,12 +212,11 @@
     if ((dp = db_lookup(dbip, comb_leaf->tr_l.tl_name, LOOKUP_QUIET)) == 
RT_DIR_NULL)
        return;
 
-    s->s_c[dp]++;
     if (s->verbosity) {
        if (comb_leaf->tr_l.tl_mat) {
-           bu_log("Found comb entry: %s[M] (Instance count: %d)\n", 
dp->d_namep, s->s_c[dp]);
+           bu_log("Found comb entry: %s[M]\n", dp->d_namep);
        } else {
-           bu_log("Found comb entry: %s (Instance count: %d)\n", dp->d_namep, 
s->s_c[dp]);
+           bu_log("Found comb entry: %s\n", dp->d_namep);
        }
        if (s->verbosity > 1) {
            struct bu_vls title = BU_VLS_INIT_ZERO;
@@ -215,6 +227,24 @@
            bu_vls_free(&title);
        }
     }
+
+    dp_i idp;
+    idp.dp = dp;
+    /* In a survey of objects we are not pushing, we need to evaluate 
+     * the object in isolation (i.e. using its global position, not the
+     * instance position.)  If we're evaluating a push operation,
+     * we're considering the instance with its evaluated matrix. */
+    if (!s->survey) {
+       MAT_COPY(idp.mat, *((mat_t *)cm));
+    } else {
+       MAT_IDN(idp.mat);
+    }
+    /* Record for each object if it's a push object or not, to make
+     * subsequent processing easier. */
+    idp.push_obj = !s->survey;
+    idp.ts_tol = s->tol;
+    if (s->s_i.find(idp) == s->s_i.end())
+       s->s_i.insert(idp);
 }
 
 void comb_cnt(struct db_i *dbip, struct directory *dp, int depth, mat_t 
*curr_mat, void *data)
@@ -289,9 +319,15 @@
     GED_CHECK_ARGC_GT_0(gedp, argc, GED_ERROR);
     struct db_i *dbip = gedp->ged_wdbp->dbip;
 
+    /* Need nref current for db_ls to work */
+    db_update_nref(dbip, &rt_uniresource);
+
     /* initialize result */
     bu_vls_trunc(gedp->ged_result_str, 0);
 
+
+    /* Based on the push arg list, walk the specified trees to identify
+     * instances involved with matrices */
     struct push_state s;
     s.verbosity = verbosity;
     s.tol = &gedp->ged_wdbp->wdb_tol;
@@ -300,7 +336,58 @@
     for (int i = 0; i < argc; i++) {
        struct directory *dp = db_lookup(dbip, argv[i], LOOKUP_NOISY);
        if (dp != RT_DIR_NULL) {
+           s.target_objs.insert(std::string(dp->d_namep));
+       }
+    }
+    std::set<std::string>::iterator s_it;
+    for (s_it = s.target_objs.begin(); s_it != s.target_objs.end(); s_it++) {
+       struct directory *dp = db_lookup(dbip, s_it->c_str(), LOOKUP_NOISY);
+       push_walk(dbip, dp, comb_cnt, NULL, &rt_uniresource, 0, &m, &s);
+    }
+
+    /* Sanity - if we didn't end up with m back at the identity matrix,
+     * something went wrong with the walk */
+    if (!bn_mat_is_equal(m, bn_mat_identity, &gedp->ged_wdbp->wdb_tol)) {
+       bu_vls_sprintf(gedp->ged_result_str, "Error - initial tree walk 
finished with non-IDN matrix.\n");
+       return GED_ERROR;
+    }
+
+
+    /* Because pushes have potentially global consequences, we must
+     * also characterize all unique object instances in the database.  That
+     * information will be needed to know if any given matrix push is self
+     * contained as-is or would require an object copy+rename to be isolated.
+     */
+    s.survey = true;
+    struct directory **all_paths;
+    int tops_cnt = db_ls(gedp->ged_wdbp->dbip, DB_LS_TOPS, NULL, &all_paths);
+    for (int i = 0; i < tops_cnt; i++) {
+       struct directory *dp = all_paths[i];
+       if (s.target_objs.find(std::string(dp->d_namep)) == s.target_objs.end())
            push_walk(dbip, dp, comb_cnt, NULL, &rt_uniresource, 0, &m, &s);
+    }
+    bu_free(all_paths, "free db_ls output");
+
+    // Once the survey walk is complete, iterate over s_i and count how many
+    // instances of each dp are present.  Any dp with multiple instances can't
+    // be pushed without a copy being made, as the dp instances represent
+    // multiple volumes in space.
+    std::set<dp_i>::iterator si_it;
+    for (si_it = s.s_i.begin(); si_it != s.s_i.end(); si_it++) {
+       const dp_i &dpi = *si_it;
+       s.s_c[dpi.dp]++;
+    }
+
+
+
+    // See what we've got...
+    for (si_it = s.s_i.begin(); si_it != s.s_i.end(); si_it++) {
+       const dp_i &dpi = *si_it;
+       if (!bn_mat_is_equal(dpi.mat, bn_mat_identity, s.tol)) {
+           std::cout << dpi.dp->d_namep << "(" << dpi.push_obj << "," << 
s.s_c[dpi.dp] << "):\n";
+           bn_mat_print(dpi.dp->d_namep, dpi.mat);
+       } else {
+           std::cout << dpi.dp->d_namep << "(" << dpi.push_obj << "," << 
s.s_c[dpi.dp] << ")\n";
        }
     }
 

This was sent by the SourceForge.net collaborative development platform, the 
world's largest Open Source development site.



_______________________________________________
BRL-CAD Source Commits mailing list
[email protected]
https://lists.sourceforge.net/lists/listinfo/brlcad-commits

Reply via email to