Revision: 78168
          http://sourceforge.net/p/brlcad/code/78168
Author:   starseeker
Date:     2021-02-02 17:09:22 +0000 (Tue, 02 Feb 2021)
Log Message:
-----------
Incorporate more full path printing into logging

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-02-02 15:27:20 UTC (rev 
78167)
+++ brlcad/trunk/src/libged/npush/npush.cpp     2021-02-02 17:09:22 UTC (rev 
78168)
@@ -58,14 +58,13 @@
  */
 class dp_i {
     public:
-       struct directory *dp;  // Instance database object
-       struct directory *parent_dp;  // Parent object
-       mat_t mat;             // Instance matrix
-       size_t ind;
+       struct directory *dp;              // Instance database object
+       struct directory *parent_dp;       // Parent object
+       mat_t mat;                         // Instance matrix
+       size_t ind;                        // Used for debugging
+       std::string iname = std::string(); // Container to hold instance name, 
if needed
+       const struct bn_tol *tol;       // Tolerance to use for matrix 
comparisons
 
-       std::string iname = std::string();     // Container to hold instance 
name, if needed
-       const struct bn_tol *ts_tol;  // Tolerance to use for matrix comparisons
-
        bool push_obj = true;  // Flag to determine if this instance is being 
pushed
        bool is_leaf = false;  // Flag to determine if this instance is a push 
leaf
 
@@ -101,11 +100,11 @@
 
            /* If the dp doesn't tell us, check the matrix. */
            int tidn, oidn;
-           if (!bn_mat_is_equal(mat, o.mat, ts_tol)) {
+           if (!bn_mat_is_equal(mat, o.mat, tol)) {
                // We want IDN matrices to be less than any others, regardless
                // of the numerics.
-               tidn = bn_mat_is_equal(mat, bn_mat_identity, ts_tol);
-               oidn = bn_mat_is_equal(o.mat, bn_mat_identity, ts_tol);
+               tidn = bn_mat_is_equal(mat, bn_mat_identity, tol);
+               oidn = bn_mat_is_equal(o.mat, bn_mat_identity, tol);
                if (tidn && !oidn) return true;
                if (oidn && !tidn) return false;
 
@@ -139,11 +138,11 @@
        bool operator==(const dp_i &o) const {
            if (dp != o.dp) return false;
            if (apply_to_solid != o.apply_to_solid) {
-               if (!bn_mat_is_equal(mat, bn_mat_identity, ts_tol) ||
-                       !bn_mat_is_equal(o.mat, bn_mat_identity, ts_tol))
+               if (!bn_mat_is_equal(mat, bn_mat_identity, tol) ||
+                       !bn_mat_is_equal(o.mat, bn_mat_identity, tol))
                    return false;
            }
-           return bn_mat_is_equal(mat, o.mat, ts_tol);
+           return bn_mat_is_equal(mat, o.mat, tol);
        }
 };
 
@@ -153,41 +152,39 @@
     /* Variables used for validity checking of specified push object(s).  The
      * target_objects set is user specified - if objects are specified that are
      * below other target objects, flag valid_push is set to false and the user
-     * gets an error report. */
+     * gets an error report.  Conveniently, that mechanism will also recognize
+     * and reject cyclic trees. */
+    bool final_check = false;
     bool valid_push = true;
+    bool walk_error = false;
+    std::set<std::string> initial_missing;
     std::set<std::string> target_objs;
-    std::set<std::string> initial_missing;
-    bool final_check = false;
-    std::string msgs;
+    struct bu_vls *msgs = NULL;
+    std::string problem_obj;
 
     /* User-supplied flags controlling tree walking behavior */
-    int max_depth = 0;
+    bool dry_run = false;
     bool stop_at_regions = false;
     bool stop_at_shapes = false;
-    bool dry_run = false;
+    int max_depth = 0;
+    int verbosity = 0;
 
     /* Containers for instance structures being built up during the push walk.
      * We do not need to duplicate these - the combination of matrix and dp
-     * uniquely identifies a volume in space - so the C++ set container is used
-     * to ensure we end up with the set of just unique dp instances after tree
-     * walking. */
+     * uniquely identifies a volume in space.  The C++ set container is used
+     * to ensure we end up with one unique dp_i per instance. */
     std::set<dp_i> instances;
 
     /* Tolerance to be used for matrix comparisons.  Typically comes from the
      * database tolerances. */
-    const struct bn_tol *tol;
+    const struct bn_tol *tol = NULL;
 
     /* Database information */
-    struct rt_wdb *wdbp;
+    struct rt_wdb *wdbp = RT_WDB_NULL;
 
-    /* Processing info */
+    /* Container for finalized database objects, used to assemble and
+     * store them prior to the database writing step. */
     std::map<struct directory *, struct rt_db_internal *> updated;
-
-    /* Debugging related data and variables */
-    int verbosity = 0;
-    std::string problem_obj;
-    bool walk_error = false;
-
 };
 
 /* Tree walks terminate at leaves.  However, what constitutes a leaf is not 
always
@@ -226,10 +223,25 @@
 }
 
 
-/* This set of walking functions does a preliminary check to ensure there are 
no
- * nested specifications of push objects supplied to the push command, in the 
case
- * where a user supplies multiple root objects to pushed.
+/* There are a variety of situations, both due to invalid user inputs and to
+ * problems with tree processing, that can result in errors.
  *
+ * This set of walking functions encapsulates a series of checks used at 
various
+ * stages of the process:
+ *
+ * 1.  A preliminary check to ensure there are no nested specifications of push
+ *     objects supplied to the push command, in the case where a user supplies
+ *     multiple root objects to pushed.
+ *
+ * 2.  A check to ensure the logic hasn't created any tree instances that don't
+ *     refer to real database objects.  This works in two stages - the initial
+ *     pass, performed as part of the initial validation walk, records any
+ *     references that were missing to begin with.  A second pass at the end
+ *     checks for any new missing references.
+ *
+ * The "mode" of the validation (beginning checks or end checks) is controlled
+ * by the "final_check" flag in the push_state container.
+ *
  * Once an invalidity is found, these routines abort and record the invalidity.
  * This is for ease of implementation and performance, but can be adjusted to
  * do a more comprehensive review if that proves worthwhile. */
@@ -276,11 +288,12 @@
            if (!s->final_check) {
                if (s->target_objs.find(std::string(dp->d_namep)) != 
s->target_objs.end()) {
                    s->valid_push = false;
-                   char *ps = db_path_to_string(dfp);
-                   std::string msg = std::string(ps) + std::string(": top 
level push object ") + std::string(dp->d_namep) + std::string(" is below top 
level object ") + std::string(dfp->fp_names[0]->d_namep) + std::string("\n");
-                   s->msgs = msg;
+                   if (s->msgs) {
+                       char *ps = db_path_to_string(dfp);
+                       bu_vls_printf(s->msgs, "W1[%s]: user specified push 
object %s is below user specified push object %s\n", ps, 
DB_FULL_PATH_CUR_DIR(dfp)->d_namep, dfp->fp_names[0]->d_namep);
+                       bu_free(ps, "path string");
+                   }
                    s->problem_obj = std::string(dp->d_namep);
-                   bu_free(ps, "path string");
                    DB_FULL_PATH_POP(dfp);
                    return;
                }
@@ -325,9 +338,19 @@
        struct rt_db_internal in;
        struct rt_comb_internal *comb;
 
-       if (rt_db_get_internal5(&in, DB_FULL_PATH_CUR_DIR(dfp), dbip, NULL, 
&rt_uniresource) < 0)
+       // Load the comb.  In the validation stage, if we can't do this report
+       // an error.
+       if (rt_db_get_internal5(&in, DB_FULL_PATH_CUR_DIR(dfp), dbip, NULL, 
&rt_uniresource) < 0) {
+           if (s->msgs) {
+               char *ps = db_path_to_string(dfp);
+               bu_vls_printf(s->msgs, "W1[%s]: rt_db_get_internal5 failure 
reading comb %s\n", ps, DB_FULL_PATH_CUR_DIR(dfp)->d_namep);
+               bu_free(ps, "path string");
+           }
+           s->valid_push = false;
            return;
+       }
 
+       // Have comb, proceed to walk tree
        comb = (struct rt_comb_internal *)in.idb_ptr;
        validate_walk_subtree(dbip, dfp, comb->tree, client_data);
        rt_db_free_internal(&in);
@@ -336,9 +359,12 @@
 }
 
 
-/* The primary walking routine, responsible for collecting information about
- * tree states.  Used for both a push walk and survey of the overall database.
- * */
+/* push_walk is responsible for identifying the set of instances we will use in
+ * push operations, as well as characterizing other parts of the database which
+ * may (depending on user settings) require awareness on the part of the
+ * processing routines to keep unrelated parts of the .g file isolated from
+ * push-related changes.
+ */
 static void
 push_walk(struct db_full_path *dfp,
        int depth,
@@ -355,11 +381,17 @@
        bool survey,
        void *client_data)
 {
+    mat_t om, nm;
+    struct push_state *s = (struct push_state *)client_data;
     struct directory *dp;
+
     dp_i dnew;
+
+    // Note - instances aren't actually defined in terms of the name or dp of
+    // their parent - it is theoretically possible to have an instance with
+    // multiple parent combs - but typically knowing the parent is the simplest
+    // way to find/inspect information related to an instance in the database.
     dnew.parent_dp = DB_FULL_PATH_CUR_DIR(dfp);
-    struct push_state *s = (struct push_state *)client_data;
-    mat_t om, nm;
 
     if (!tp)
        return;
@@ -387,22 +419,33 @@
            }
            bn_mat_mul(*curr_mat, om, nm);
 
-           if (s->verbosity > 2) {
+           /* Depending on use verbosity settings, report various information 
about
+            * the current state of the tree walk */
+           if (s->verbosity > 2 && s->msgs) {
                char *ps = db_path_to_string(dfp);
                if (tp->tr_l.tl_mat && !bn_mat_is_equal(*curr_mat, 
bn_mat_identity, s->tol)) {
-                   bu_log("Found %s->[M]%s\n", ps, dp->d_namep);
+                   bu_vls_printf(s->msgs, "W2[%s]: found [M]%s\n", ps, 
dp->d_namep);
                    if (s->verbosity > 3) {
-                       bn_mat_print(tp->tr_l.tl_name, *curr_mat);
+                       struct bu_vls title = BU_VLS_INIT_ZERO;
+                       bu_vls_sprintf(&title, "W2[%s]: %s instance matrix", 
ps, dp->d_namep);
+                       bn_mat_print_vls(bu_vls_cstr(&title), *curr_mat, 
s->msgs);
+                       bu_vls_free(&title);
                    }
                } else {
-                   bu_log("Found %s->%s\n", ps, dp->d_namep);
+                   bu_vls_printf(s->msgs, "W2[%s]: found %s\n", ps, 
dp->d_namep);
                }
+               if (s->verbosity > 3) {
+                   struct bu_vls title = BU_VLS_INIT_ZERO;
+                   bu_vls_sprintf(&title, "W2[%s]: %s current overall path 
matrix", ps, dp->d_namep);
+                   bn_mat_print_vls(bu_vls_cstr(&title), *curr_mat, s->msgs);
+                   bu_vls_free(&title);
+               }
                bu_free(ps, "path string");
            }
 
-           // Define the instance container
+           // Define the instance container for the (potentially) new instance.
            dnew.dp = dp;
-           dnew.ts_tol = s->tol;
+           dnew.tol = s->tol;
            dnew.push_obj = !(survey);
            if (!survey) {
                MAT_COPY(dnew.mat, *curr_mat);
@@ -410,6 +453,8 @@
                MAT_COPY(dnew.mat, nm);
            }
 
+           // A "push leaf" is the termination point below which we will not
+           // propagate changes encoded in matrices.
            if (is_push_leaf(dp, depth, s, survey)) {
 
                // Flag as leaf
@@ -419,27 +464,36 @@
                if (!DB_FULL_PATH_LEN(dfp))
                    return;
 
-               if (!survey) {
-                   if (!(dp->d_flags & RT_DIR_COMB) && (!s->max_depth || 
depth+1 <= s->max_depth) && !s->stop_at_shapes) {
-                       // If dp is a solid, we're not depth limited, we're not
-                       // stopping above shapes, and the solid supports it we
-                       // apply the matrix to the primitive itself.  The comb
-                       // reference will use the IDN matrix.
-                       if (s->verbosity > 2) {
-                           char *ps = db_path_to_string(dfp);
-                           bu_log("Push leaf (finalize matrix or solid 
params): %s->%s\n", ps, dp->d_namep);
-                           bu_free(ps, "path string");
-                       }
-                       dnew.apply_to_solid = true;
+               // If dp is a solid, we're not depth limited, we're not
+               // stopping above shapes, and the solid supports it we apply
+               // the matrix to the primitive itself.  The comb reference will
+               // use the IDN matrix.
+               if (!survey && !(dp->d_flags & RT_DIR_COMB) &&
+                       (!s->max_depth || depth+1 <= s->max_depth) && 
!s->stop_at_shapes) {
+                   if (s->verbosity > 2 && s->msgs) {
+                       char *ps = db_path_to_string(dfp);
+                       bu_vls_printf(s->msgs, "W2[%s]: push leaf (finalize 
matrix or solid params): %s\n", ps, dp->d_namep);
+                       bu_free(ps, "path string");
                    }
+                   dnew.apply_to_solid = true;
                }
 
-               // If we haven't already inserted an identical instance, record 
this new
-               // entry.  (Note that we're not concerned with the
-               // boolean set aspects of the tree's definition here, only 
unique volumes in
-               // space, so this set does not exactly mimic the original comb 
tree structure.)
+               // If we haven't already inserted an identical instance, record
+               // this new entry.  (Note that we're not concerned with the
+               // boolean set aspects of the tree's definition here, only
+               // unique volumes in space, so the instance set does not
+               // exactly mimic the original comb tree structure.)
                if (s->instances.find(dnew) == s->instances.end()) {
                    s->instances.insert(dnew);
+                   if (s->verbosity > 3 && s->msgs) {
+                       struct bu_vls title = BU_VLS_INIT_ZERO;
+                       char *ps = db_path_to_string(dfp);
+                       bu_vls_printf(s->msgs, "W2[%s]: %s is a new unique 
instance\n", ps, dp->d_namep);
+                       bu_vls_sprintf(&title, "W2[%s]: instance matrix", ps);
+                       bn_mat_print_vls(bu_vls_cstr(&title), dnew.mat, 
s->msgs);
+                       bu_vls_free(&title);
+                       bu_free(ps, "path string");
+                   }
                }
 
                // Even though this is a leaf, we need to continue if we have a
@@ -450,9 +504,9 @@
                // comb will need to be copied.
                if (dp->d_flags & RT_DIR_COMB) {
                    /* Process branch's tree */
-                   if (s->verbosity > 1 && !survey) {
+                   if (!survey && s->verbosity > 4 && s->msgs) {
                        char *ps = db_path_to_string(dfp);
-                       bu_log("Switching from push to survey - non-shape leaf 
%s->%s found\n", ps, dp->d_namep);
+                       bu_vls_printf(s->msgs, "W2[%s]: switching from push to 
survey - non-shape leaf %s found\n", ps, dp->d_namep);
                        bu_free(ps, "path string");
                    }
                    db_add_node_to_full_path(dfp, dp);
@@ -468,21 +522,31 @@
                // of a push - the matrix ultimately applied will be an IDN
                // matrix, but the current tree matrix is recorded to allow
                // instance lookups later in processing.
-               if (!survey && s->verbosity > 2) {
+               if (!survey && s->msgs && s->verbosity > 4) {
                    char *ps = db_path_to_string(dfp);
-                   bu_log("Pushed comb instance: %s->%s\n", ps, dp->d_namep);
+                   bu_vls_printf(s->msgs, "W2[%s]: pushed comb instance %s\n", 
ps, dp->d_namep);
                    bu_free(ps, "path string");
                }
                dnew.is_leaf = false;
            }
 
-           if (survey && s->verbosity > 2) {
+           if (survey && s->msgs && s->verbosity > 4) {
                char *ps = db_path_to_string(dfp);
-               bu_log("Survey comb instance: %s->%s\n", ps, dp->d_namep);
+               bu_vls_printf(s->msgs, "W2[%s]: survey comb instance %s\n", ps, 
dp->d_namep);
                bu_free(ps, "path string");
            }
+
            if (s->instances.find(dnew) == s->instances.end()) {
                s->instances.insert(dnew);
+               if (s->verbosity > 3 && s->msgs) {
+                   struct bu_vls title = BU_VLS_INIT_ZERO;
+                   char *ps = db_path_to_string(dfp);
+                   bu_vls_printf(s->msgs, "W2[%s]: %s is a new unique 
instance\n", ps, dp->d_namep);
+                   bu_vls_sprintf(&title, "W2[%s]: instance matrix", ps);
+                   bn_mat_print_vls(bu_vls_cstr(&title), dnew.mat, s->msgs);
+                   bu_vls_free(&title);
+                   bu_free(ps, "path string");
+               }
            }
 
            /* Process branch's tree */
@@ -591,7 +655,7 @@
            // Look up the dpi for this comb+curr_mat combination.
            ldpi.dp = dp;
            MAT_COPY(ldpi.mat, *curr_mat);
-           ldpi.ts_tol = s->tol;
+           ldpi.tol = s->tol;
            if (!(dp->d_flags & RT_DIR_COMB) && (!s->max_depth || depth+1 <= 
s->max_depth) && !s->stop_at_shapes) {
                ldpi.apply_to_solid = true;
            }
@@ -921,6 +985,7 @@
     s.stop_at_shapes = (to_solids) ? true : false;
     s.dry_run = (dry_run) ? true : false;
     s.wdbp = gedp->ged_wdbp;
+    s.msgs = gedp->ged_result_str;
     for (int i = 0; i < argc; i++) {
        s.target_objs.insert(std::string(argv[i]));
     }
@@ -940,7 +1005,6 @@
        db_add_node_to_full_path(dfp, dp);
        validate_walk(dbip, dfp, &s);
        if (!s.valid_push) {
-           bu_vls_printf(gedp->ged_result_str, "%s", s.msgs.c_str());
            if (BU_STR_EQUAL(dp->d_namep, s.problem_obj.c_str())) {
                bu_vls_printf(gedp->ged_result_str, "NOTE: cyclic path found: 
%s is below itself", dp->d_namep);
            }
@@ -966,10 +1030,9 @@
     // push operations would have on the comb trees and solids.
     mat_t m;
     for (s_it = s.target_objs.begin(); s_it != s.target_objs.end(); s_it++) {
+       MAT_IDN(m);
        struct directory *dp = db_lookup(dbip, s_it->c_str(), LOOKUP_NOISY);
        if (dp != RT_DIR_NULL && (dp->d_flags & RT_DIR_COMB)) {
-           MAT_IDN(m);
-
            struct db_full_path *dfp;
            BU_GET(dfp, struct db_full_path);
            db_full_path_init(dfp);
@@ -1181,7 +1244,7 @@
     // For debugging purposes, with a high enough verbosity print out the state
     // of the instances set ahead of the final tree walk so we know what to
     // expect.
-    if (s.verbosity > 4) {
+    if (s.verbosity > 4 && s.msgs) {
        std::set<dp_i>::iterator in_it;
        bu_log("\n\n\nDirectory pointer instance set (final state before 
application walk):\n\n");
        for (in_it = s.instances.begin(); in_it != s.instances.end(); in_it++) {
@@ -1190,19 +1253,19 @@
                continue;
            if (dpi.iname.length()) {
                if (!dpi.is_leaf && (dpi.dp->d_flags & RT_DIR_COMB)) {
-                   bu_log("%s tree edited && matrix to IDN\n", 
dpi.iname.c_str());
+                   bu_vls_printf(s.msgs, "%s tree edited && matrix to IDN\n", 
dpi.iname.c_str());
                }
                if (dpi.is_leaf && !bn_mat_is_equal(dpi.mat, bn_mat_identity, 
s.tol)) {
-                   bu_log("%s\n", dpi.iname.c_str());
-                   bn_mat_print("applied", dpi.mat);
+                   bu_vls_printf(s.msgs, "%s\n", dpi.iname.c_str());
+                   bn_mat_print_vls("applied", dpi.mat, s.msgs);
                }
            } else {
                if (!dpi.is_leaf && (dpi.dp->d_flags & RT_DIR_COMB)) {
-                   bu_log("%s matrix to IDN\n", dpi.dp->d_namep);
+                   bu_vls_printf(s.msgs, "%s matrix to IDN\n", 
dpi.dp->d_namep);
                }
                if (dpi.is_leaf && !bn_mat_is_equal(dpi.mat, bn_mat_identity, 
s.tol)) {
-                   bu_log("%s\n", dpi.dp->d_namep);
-                   bn_mat_print("applied", dpi.mat);
+                   bu_vls_printf(s.msgs, "%s\n", dpi.dp->d_namep);
+                   bn_mat_print_vls("applied", dpi.mat, s.msgs);
                }
            }
        }
@@ -1223,7 +1286,7 @@
            dp_i ldpi;
            ldpi.dp = dp;
            MAT_IDN(ldpi.mat);
-           ldpi.ts_tol = s.tol;
+           ldpi.tol = s.tol;
 
            struct db_full_path *dfp;
            BU_GET(dfp, struct db_full_path);

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