Revision: 78145
http://sourceforge.net/p/brlcad/code/78145
Author: starseeker
Date: 2021-01-29 20:14:27 +0000 (Fri, 29 Jan 2021)
Log Message:
-----------
Ray diffing isn't enough - also need to check for matrix differences in the
tree.
Modified Paths:
--------------
brlcad/trunk/src/libged/tests/push.cpp
Modified: brlcad/trunk/src/libged/tests/push.cpp
===================================================================
--- brlcad/trunk/src/libged/tests/push.cpp 2021-01-29 18:59:12 UTC (rev
78144)
+++ brlcad/trunk/src/libged/tests/push.cpp 2021-01-29 20:14:27 UTC (rev
78145)
@@ -37,9 +37,121 @@
#include "bu/app.h"
#include "bu/path.h"
#include "bu/str.h"
+#include "rt/db_diff.h"
#include "ged.h"
+/* Push checking is a bit quirky - we want to check matrices and tree
structure in
+ * comb instances, but not instance names. We also need to compare solid
leaves,
+ * but not names. The following is a custom routine for this purpose */
+static void check_walk(bool *diff, struct db_i *dbip, struct directory *dp1,
struct directory *dp2);
static void
+check_walk_subtree(bool *diff, struct db_i *dbip, union tree *tp1, union tree
*tp2)
+{
+ bool idn1, idn2;
+ struct directory *dp1, *dp2;
+
+ if (!diff)
+ return;
+
+ if ((!tp1 && tp2) || (tp1 && !tp2)) {
+ (*diff) = true;
+ return;
+ }
+
+ if (tp1->tr_op != tp2->tr_op) {
+ (*diff) = true;
+ return;
+ }
+
+ switch (tp1->tr_op) {
+ case OP_DB_LEAF:
+ idn1 = (!tp1->tr_l.tl_mat || bn_mat_is_identity(tp1->tr_l.tl_mat));
+ idn2 = (!tp2->tr_l.tl_mat || bn_mat_is_identity(tp2->tr_l.tl_mat));
+ if (idn1 != idn2) {
+ (*diff) = true;
+ return;
+ }
+ if (tp1->tr_l.tl_mat && tp2->tr_l.tl_mat) {
+ if (!bn_mat_is_equal(tp1->tr_l.tl_mat, tp2->tr_l.tl_mat,
&dbip->dbi_wdbp->wdb_tol)) {
+ (*diff) = true;
+ return;
+ }
+ }
+
+ dp1 = db_lookup(dbip, tp1->tr_l.tl_name, LOOKUP_NOISY);
+ dp2 = db_lookup(dbip, tp2->tr_l.tl_name, LOOKUP_NOISY);
+
+ check_walk(diff, dbip, dp1, dp2);
+
+ break;
+ case OP_UNION:
+ case OP_INTERSECT:
+ case OP_SUBTRACT:
+ case OP_XOR:
+ check_walk_subtree(diff, dbip, tp1->tr_b.tb_left,
tp2->tr_b.tb_left);
+ check_walk_subtree(diff, dbip, tp1->tr_b.tb_right,
tp2->tr_b.tb_right);
+ break;
+ default:
+ bu_log("check_walk_subtree: unrecognized operator %d\n",
tp1->tr_op);
+ bu_bomb("check_walk_subtree: unrecognized operator\n");
+ }
+}
+
+static void
+check_walk(bool *diff,
+ struct db_i *dbip,
+ struct directory *dp1,
+ struct directory *dp2)
+{
+ if ((!dp1 && !dp2) || !diff || (*diff)) {
+ return; /* nothing to do */
+ }
+ if ((dp1 == RT_DIR_NULL && dp2 != RT_DIR_NULL) || (dp1 != RT_DIR_NULL &&
dp2 == RT_DIR_NULL)) {
+ *diff = true;
+ return;
+ }
+ if (dp1 == RT_DIR_NULL && dp2 == RT_DIR_NULL) {
+ return;
+ }
+ if (dp1->d_flags != dp2->d_flags) {
+ *diff = true;
+ return;
+ }
+
+ if (dp1->d_flags & RT_DIR_COMB) {
+
+ struct rt_db_internal in1, in2;
+ struct rt_comb_internal *comb1, *comb2;
+
+ if (rt_db_get_internal5(&in1, dp1, dbip, NULL, &rt_uniresource) < 0) {
+ *diff = true;
+ return;
+ }
+
+ if (rt_db_get_internal5(&in2, dp2, dbip, NULL, &rt_uniresource) < 0) {
+ *diff = true;
+ return;
+ }
+
+ comb1 = (struct rt_comb_internal *)in1.idb_ptr;
+ comb2 = (struct rt_comb_internal *)in2.idb_ptr;
+ check_walk_subtree(diff, dbip, comb1->tree, comb2->tree);
+ rt_db_free_internal(&in1);
+ rt_db_free_internal(&in2);
+
+ return;
+ }
+
+ /* If we have two solids, use db_diff_dp */
+ int dr = db_diff_dp(dbip, dbip, dp1, dp2, &dbip->dbi_wdbp->wdb_tol,
DB_COMPARE_ALL, NULL);
+ if (dr != DIFF_UNCHANGED) {
+ std::cout << "solids " << dp1->d_namep << " and " << dp2->d_namep << "
differ\n";
+ *diff = true;
+ }
+}
+
+
+static void
npush_usage(struct bu_vls *str, struct bu_opt_desc *d) {
char *option_help = bu_opt_describe(d, NULL);
bu_vls_sprintf(str, "Usage: ged_push_test [options] control.g
working.g\n");
@@ -146,6 +258,8 @@
// Make sure our reference counts are up to date
db_update_nref(gedp->ged_wdbp->dbip, &rt_uniresource);
+ // TODO - cache the initial list of tops objects - should not change,
+ // regardless of what push operations are used
// Perform the specified push operation on all example objects
for (size_t i = 0; i <= 16; i++) {
@@ -167,6 +281,9 @@
gargv[gargc-1] = NULL;
bu_argv_free((size_t)gargc, gargv);
+ // TODO - re-read tops objects, compare lists - should match
+
+
// dbconcat the control file into the current database, with a prefix
const char *dbcargv[4];
dbcargv[0] = "dbconcat";
@@ -175,19 +292,54 @@
dbcargv[3] = NULL;
ged_concat(gedp, 3, (const char **)dbcargv);
- // object names may not be identical - what we are concerned with is
- // that the geometry shapes remain unchanged from what is expected (or,
- // in a few specific cases, we check that differences are found.)
- // Use the libged raytracing based gdiff to check this.
+ // object names may not be identical - what we are concerned with is that
+ // the geometry shapes remain unchanged from what is expected (or, in a few
+ // specific cases, we check that differences are found.) Use the libged
+ // raytracing based gdiff and a parallel tree walk to check this.
+ bool have_diff_vol = false;
+ bool have_diff_struct = false;
+ const char *gdiffargv[4];
+ gdiffargv[0] = "gdiff";
+ for (size_t i = 0; i <= 16; i++) {
+ std::ostringstream ss;
+ ss << "sph_";
+ ss << std::setfill('0') << std::setw(3) << i;
+ std::string oname = ss.str();
+ char *gobj = bu_strdup(oname.c_str());
+ std::string cname = std::string("ctrl_") + oname;
+ char *cobj = bu_strdup(cname.c_str());
+ gdiffargv[1] = cobj;
+ gdiffargv[2] = gobj;
+ bu_vls_trunc(gedp->ged_result_str, 0);
+ ged_gdiff(gedp, 3, (const char **)gdiffargv);
+ if (!BU_STR_EQUAL(bu_vls_cstr(gedp->ged_result_str), "0")) {
+ std::cout << cobj << " and " << gobj << " define different
volumes\n";
+ have_diff_vol = true;
+ }
+ struct directory *dp1 = db_lookup(gedp->ged_wdbp->dbip, cobj,
LOOKUP_NOISY);
+ struct directory *dp2 = db_lookup(gedp->ged_wdbp->dbip, gobj,
LOOKUP_NOISY);
+ check_walk(&have_diff_struct, gedp->ged_wdbp->dbip, dp1, dp2);
+ if (have_diff_struct)
+ std::cout << cobj << " and " << gobj << " differ structurally\n";
+ bu_free(cobj, "ctrl objname");
+ bu_free(gobj, "push objname");
+ }
- // Remove the copy of the .g file
- //std::remove(bu_vls_cstr(&gfile));
+ if (!have_diff_vol && !have_diff_struct) {
+ // Remove the copy of the .g file
+ //std::remove(bu_vls_cstr(&gfile));
+ }
+
// Clean up
bu_vls_free(&gfile);
bu_vls_free(&gbasename);
bu_vls_free(&wdir);
+ if (have_diff_vol || have_diff_struct) {
+ return -1;
+ }
+
return 0;
}
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