Revision: 78103
          http://sourceforge.net/p/brlcad/code/78103
Author:   starseeker
Date:     2021-01-22 15:47:22 +0000 (Fri, 22 Jan 2021)
Log Message:
-----------
checkpoint

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-21 22:50:53 UTC (rev 
78102)
+++ brlcad/trunk/src/libged/npush/npush.cpp     2021-01-22 15:47:22 UTC (rev 
78103)
@@ -25,8 +25,10 @@
 
 #include "common.h"
 
+#include <algorithm>
 #include <set>
 #include <map>
+#include <queue>
 #include <string>
 #include <vector>
 
@@ -55,9 +57,10 @@
 class dp_i {
     public:
        struct directory *dp;  // Instance database object
+       struct directory *parent_dp;  // Parent object
        mat_t mat;             // Instance matrix
 
-       std::string iname;     // Container to hold instance name, if needed
+       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
@@ -224,7 +227,6 @@
     bool stop_at_shapes = false;
 
     /* Primary containers holding information gathered during tree walk */
-    std::set<combtree_i> t_i;
     std::map<struct directory *, std::set<struct directory *>> comb_parents;
 
     /* Containers for intermediate combtree structures being
@@ -394,6 +396,7 @@
     struct bu_vls title = BU_VLS_INIT_ZERO;
     combtree_i tnew;
     dp_i dnew;
+    dnew.parent_dp = parent_dp;
     struct push_state *s = (struct push_state *)client_data;
     mat_t om, nm;
 
@@ -690,6 +693,10 @@
      * 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.
+     *
+     * TODO - this needs to be only be enabled with an option, so we can
+     * replicate current (unsafe) push behavior that doesn't take cognizance of
+     * the .g contents beyond the specified push tree.
      */
     struct directory **all_paths;
     int tops_cnt = db_ls(gedp->ged_wdbp->dbip, DB_LS_TOPS, NULL, &all_paths);
@@ -701,46 +708,106 @@
     bu_free(all_paths, "free db_ls output");
 
 
-    /* Build a set of unique combtrees */
+    /* Build a set of unique combtrees, and create a vector from that set.  The
+     * former guarantees uniqueness, the latter is simpler to work with when it
+     * comes to manipulating elements (which may be necessary in later steps.)
+     * We do this now so instance iterations can be simpler, but we also need
+     * the final names of unique instances before we will know what updates are
+     * needed to trees - hence those instances must be identified first. */
+    std::set<combtree_i> treeset(s.ct.begin(), s.ct.end());
+    std::vector<combtree_i> uniq_trees(treeset.size());
+    std::copy(treeset.begin(), treeset.end(), uniq_trees.begin());
+    treeset.clear();
+
     std::cout << "tree vect size: " << s.ct.size() << "\n";
-    for (size_t i = 0; i < s.ct.size(); i++) {
-       s.t_i.insert(s.ct[i]);
+    std::cout << "unique tree cnt: " << uniq_trees.size() << "\n";
+
+    /* We do know enough now, however, to build up information about unique
+     * trees associated with each comb dp.  This is how we will identify
+     * combinations that require copies, and may potentially propagate new
+     * trees up their chains. */
+    std::map<struct directory *, std::vector<size_t>> t_cnt;
+    for (size_t i = 0; i < uniq_trees.size(); i++) {
+       t_cnt[uniq_trees[i].dp].push_back(i);
     }
-    std::cout << "tree set size: " << s.t_i.size() << "\n";
 
-    /* Iterate over unique combtrees and build a set of unique instances */
+    // Temporary debugging - print status of unique tree check
+    std::map<struct directory *, std::vector<size_t>>::iterator ti_it;
+    for (ti_it = t_cnt.begin(); ti_it != t_cnt.end(); ti_it++) {
+       struct directory *cdp = ti_it->first;
+       if (ti_it->second.size() > 1) {
+           bu_log("Comb %s has %zd different trees\n", cdp->d_namep, 
ti_it->second.size());
+       }
+    }
+
+    // Iterate over combtrees and build a set of unique instances.
     std::set<dp_i> s_i;
-    std::set<combtree_i>::iterator tr_it;
-    std::map<struct directory *, int> t_cnt;
     size_t icnt = 0;
-    for (tr_it = s.t_i.begin(); tr_it != s.t_i.end(); tr_it++) {
-       const combtree_i &t = *tr_it;
-       s_i.insert(t.t.begin(), t.t.end());
-       icnt += t.t.size();
-       t_cnt[t.dp]++;
+    for (size_t i = 0; i < uniq_trees.size(); i++) {
+       s_i.insert(uniq_trees[i].t.begin(), uniq_trees[i].t.end());
+       icnt += uniq_trees[i].t.size();
     }
+    std::vector<dp_i> uniq_instances(s_i.size());
+    std::copy(s_i.begin(), s_i.end(), uniq_instances.begin());
+    s_i.clear();
+
+
     std::cout << "all set size: " << icnt << "\n";
     std::cout << "instance set size: " << s_i.size() << "\n";
-    std::map<struct directory *, int>::iterator ti_it;
-    for (ti_it = t_cnt.begin(); ti_it != t_cnt.end(); ti_it++) {
-       if (ti_it->second > 1) {
-           bu_log("Comb %s has %d different trees\n", ti_it->first->d_namep, 
ti_it->second);
+
+
+    // Iterate over unique instances and count how many instances of each dp
+    // are present.  Any dp with multiple associated instances can't be pushed
+    // without a copy being made, as the unique dp instances represent multiple
+    // distinct volumes in space.
+    std::map<struct directory *, std::vector<size_t>> i_cnt;
+    for (size_t i = 0; i < uniq_instances.size(); i++) {
+       i_cnt[uniq_instances[i].dp].push_back(i);
+    }
+
+    // If we don't have force-push on, and we have non-unique mapping between
+    // dp pointers and instances, we can't proceed.
+    if (!xpush) {
+       bool conflict = false;
+       struct bu_vls msgs = BU_VLS_INIT_ZERO;
+       for (size_t i = 0; i < uniq_instances.size(); i++) {
+           const dp_i &dpi = uniq_instances[i];
+           if (dpi.push_obj) {
+               if (i_cnt[dpi.dp].size() > 1) {
+
+                   // This is the condition where xpush is needed - we can't
+                   // proceed.
+                   conflict = true;
+
+                   // If we're not being verbose, the first failure means we
+                   // can just immediately bail.
+                   if (!verbosity) {
+                       bu_vls_printf(gedp->ged_result_str, "Operation failed - 
force not enabled and one or more solids are being moved in conflicting 
directions by multiple comb instances.");
+                       return GED_ERROR;
+                   }
+
+                   // If verbosity is enabled, itemize the failures
+                   bu_vls_printf(&msgs, "Conflicting instance: %s->%s:\n", 
dpi.parent_dp->d_namep, dpi.dp->d_namep);
+                   // TODO - print matrix
+               }
+           }
        }
+       if (conflict) {
+           bu_vls_printf(gedp->ged_result_str, "Operation failed - force not 
enabled and one or more solids are being moved in conflicting directions by 
multiple comb instances.");
+           bu_vls_free(&msgs);
+           return GED_ERROR;
+       }
+       bu_vls_free(&msgs);
     }
+ 
 
+
+
     // Any combs that have more than one associated tree indicate that the comb
-    // needs to be duplicated to express both trees.  This has potential
-    // implications for parent combs if those parents are used outside the push
-    // tree - if they are, they can't be edited without global implications.
-    // Comb tree editing will have to propagate back up the tree until a comb
-    // is reached that is not used elsewhere in the database - if a new comb
-    // must replace an old one, that change must be propagated to ensure 
locality.
-    //
-    // Even without locality, new comb introductions need to be propagated back
-    // "up" the comb tree to see if any additional parent combs no longer have
-    // unique trees.  The termination criteria ("ready to alter trees and 
objects")
-    // would be when iterative propagation of such changes no longer introduces
-    // additional new non-unique comb trees.
+    // needs to be duplicated to express both trees.  These changes may need to
+    // be propagated back "up" the comb tree if any additional parent combs no
+    // longer have unique trees as a consequence of instances being pointed to
+    // new comb copies.
     // 
     // First thought - for each comb db, store a set of its "parent" dps.  
Then,
     // when a comb must be renamed, check its parents' instances for any uses
@@ -748,23 +815,16 @@
     // another matrix is being applied.)  If other instances exist, a new 
combtree
     // instance for the parent is needed and the propagation continues.
 
-    // 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::map<struct directory *, int> s_c;
-    std::set<dp_i>::iterator si_it;
-    for (si_it = s_i.begin(); si_it != s_i.end(); si_it++) {
-       const dp_i &dpi = *si_it;
-       s_c[dpi.dp]++;
-    }
 
+
+
+
     std::map<struct directory *, std::vector<dp_i>> dpref;
     std::set<dp_i> bpush;
-    for (si_it = s_i.begin(); si_it != s_i.end(); si_it++) {
-       const dp_i *dpi = &(*si_it);
-       if (dpi->push_obj) {
-           if (s_c[dpi->dp] > 1) {
+    for (size_t i = 0; i < uniq_instances.size(); i++) {
+       const dp_i &dpi = uniq_instances[i];
+       if (dpi.push_obj) {
+           if (i_cnt[dpi.dp].size() > 1) {
                // We don't need (or particularly want) to rename the first 
instance,
                // particularly if that instance is an IDN case.  The dp_i 
sorting
                // should put any IDN instance at the beginning, so when 
processing
@@ -776,10 +836,10 @@
                // instance of the referenced object survives unaltered.  In 
that case,
                // the original unaltered instance should retain the name and 
the IDN
                // instance does need to be renamed...
-               dpref[dpi->dp].push_back(*dpi);
+               dpref[dpi.dp].push_back(dpi);
            } else {
-               if (!bn_mat_is_equal(dpi->mat, bn_mat_identity, s.tol))
-                   bpush.insert(*dpi);
+               if (!bn_mat_is_equal(dpi.mat, bn_mat_identity, s.tol))
+                   bpush.insert(dpi);
            }
        }
     }

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