Revision: 77303
          http://sourceforge.net/p/brlcad/code/77303
Author:   starseeker
Date:     2020-10-01 13:15:27 +0000 (Thu, 01 Oct 2020)
Log Message:
-----------
Merge from trunk - r77220 through r77302

Modified Paths:
--------------
    brlcad/branches/bioh/NEWS
    brlcad/branches/bioh/TODO
    brlcad/branches/bioh/bench/pixcmp.c
    brlcad/branches/bioh/bench/run.sh
    brlcad/branches/bioh/doc/docbook/CMakeLists.txt
    brlcad/branches/bioh/doc/docbook/system/mann/analyze.xml
    brlcad/branches/bioh/doc/docbook/system/mann/kill.xml
    brlcad/branches/bioh/doc/legal/embedded/SPSR.txt
    brlcad/branches/bioh/doc/legal/other/CMakeLists.txt
    brlcad/branches/bioh/include/ged/commands.h
    brlcad/branches/bioh/src/conv/fast4-g.c
    brlcad/branches/bioh/src/libbrep/CMakeLists.txt
    brlcad/branches/bioh/src/libbrep/boolean.cpp
    brlcad/branches/bioh/src/libbrep/intersect.cpp
    brlcad/branches/bioh/src/libbrep/tests/CMakeLists.txt
    brlcad/branches/bioh/src/libged/analyze/CMakeLists.txt
    brlcad/branches/bioh/src/libged/brep/CMakeLists.txt
    brlcad/branches/bioh/src/libged/brep/brep.cpp
    brlcad/branches/bioh/src/libged/brep/ged_brep.h
    brlcad/branches/bioh/src/libged/exec_mapping.cpp
    brlcad/branches/bioh/src/libged/kill/kill.c
    brlcad/branches/bioh/src/libged/pnts_util.c
    brlcad/branches/bioh/src/libged/pnts_util.h
    brlcad/branches/bioh/src/libged/tests/CMakeLists.txt
    brlcad/branches/bioh/src/libtclcad/commands.c
    brlcad/branches/bioh/src/other/libspsr/Src/PointStream.h
    brlcad/branches/bioh/src/other/libspsr/Src/PointStream.inl
    brlcad/branches/bioh/src/other/libspsr/Src/PoissonRecon.cpp
    brlcad/branches/bioh/src/other/libspsr/Src/SPSR.cpp
    brlcad/branches/bioh/src/other/libspsr/Src/SurfaceTrimmer.cpp
    brlcad/branches/bioh/src/other/libspsr.dist
    brlcad/branches/bioh/src/tclscripts/lib/Ged.tcl

Added Paths:
-----------
    brlcad/branches/bioh/doc/docbook/devguides/
    brlcad/branches/bioh/src/libbrep/brep_defines.h
    brlcad/branches/bioh/src/libbrep/debug_plot.cpp
    brlcad/branches/bioh/src/libbrep/debug_plot.h
    brlcad/branches/bioh/src/libbrep/tests/ppx.cpp
    brlcad/branches/bioh/src/libged/analyze/analyze.cpp
    brlcad/branches/bioh/src/libged/analyze/arb8.cpp
    brlcad/branches/bioh/src/libged/analyze/arbn.cpp
    brlcad/branches/bioh/src/libged/analyze/ars.cpp
    brlcad/branches/bioh/src/libged/analyze/ged_analyze.h
    brlcad/branches/bioh/src/libged/analyze/op_pnts_vol.cpp
    brlcad/branches/bioh/src/libged/analyze/sketch.cpp
    brlcad/branches/bioh/src/libged/analyze/superell.cpp
    brlcad/branches/bioh/src/libged/analyze/util.cpp
    brlcad/branches/bioh/src/libged/brep/dplot.c
    brlcad/branches/bioh/src/libged/brep/dplot_parser.lemon
    brlcad/branches/bioh/src/libged/brep/dplot_reader.c
    brlcad/branches/bioh/src/libged/brep/dplot_reader.h
    brlcad/branches/bioh/src/libged/brep/dplot_scanner.perplex
    brlcad/branches/bioh/src/libged/tests/pnts_in_out.g
    brlcad/branches/bioh/src/other/libspsr/Src/PlyVertexMini.h

Removed Paths:
-------------
    brlcad/branches/bioh/doc/legal/other/SPSR.txt
    brlcad/branches/bioh/src/libged/analyze/analyze.c
    brlcad/branches/bioh/src/other/libspsr/Src/Ply.h
    brlcad/branches/bioh/src/other/libspsr/Src/PlyFile.cpp

Property Changed:
----------------
    brlcad/branches/bioh/
    brlcad/branches/bioh/NEWS
    brlcad/branches/bioh/bench/
    brlcad/branches/bioh/doc/
    brlcad/branches/bioh/include/
    brlcad/branches/bioh/src/libged/kill/kill.c
    brlcad/branches/bioh/src/other/
    brlcad/branches/bioh/src/other/libspsr/

Index: brlcad/branches/bioh
===================================================================
--- brlcad/branches/bioh        2020-10-01 13:13:00 UTC (rev 77302)
+++ brlcad/branches/bioh        2020-10-01 13:15:27 UTC (rev 77303)

Property changes on: brlcad/branches/bioh
___________________________________________________________________
Modified: svn:mergeinfo
## -1,5 +1,6 ##
 
/brlcad/branches/RELEASE:57439,57447-57860,69901-69913,70323-70333,71915-72242,72525-72534,72826-72858,74376-74454,74964-75140,75372-75685,76001-76451,76693-76768,77107-77132,77145-77155
-/brlcad/branches/brep-debug:61373,61375,61404,61427,61429,61470,61544,61567,61576,61999,62018,62094,62098,62107,62117,62406,62416-62519,62521-62584,62593-62614,62623,62658,62660-62674,62681-62771,62876,62901,62907,62910,62925,62928,62931-63025,63027,63051,63054-63056,63069,63071-63073,63122,63160-63161,63165,63171,63184,63187,63189-63190,63193-63196,63200,63202,63205-63210,63213,63219-63225,63232-63233,63236,63238,63338,63350-63353,63481,63618,63669,64173-64174,64176-64177,64229-64233,64242,64244,64360-64362,65165,65245,65249,65334,65833-65834,66370-66375,66931-66932,66934,67012-67015,67018-67019,67021-67022,67406,67740,67746-67748,67950,67952,68144-68145,68636,68640-68643,68820,69081,69109,69168,69206,69289,69346,69460-69461,69582-69583,69719-69721,69857-69859,69927,69995-69996,70148-70149,70347-70349,70377,70526-70527,71006-71007,71009-71022,71046-71047,71049,71096-71100
+/brlcad/branches/analyze_cmd:76836-77221
+/brlcad/branches/brep-debug:61373,61375,61404,61427,61429,61470,61544,61567,61576,61999,62018,62094,62098,62107,62117,62406,62416-62519,62521-62584,62593-62614,62623,62658,62660-62674,62681-62771,62876,62901,62907,62910,62925,62928,62931-63025,63027,63051,63054-63056,63069,63071-63073,63122,63160-63161,63165,63171,63184,63187,63189-63190,63193-63196,63200,63202,63205-63210,63213,63219-63225,63232-63233,63236,63238,63338,63350-63353,63481,63618,63669,64173-64174,64176-64177,64229-64233,64242,64244,64360-64362,65165,65245,65249,65334,65833-65834,66370-66375,66931-66932,66934,67012-67015,67018-67019,67021-67022,67406,67740,67746-67748,67950,67952,68144-68145,68636,68640-68643,68820,69081,69109,69168,69206,69289,69346,69460-69461,69582-69583,69719-69721,69857-69859,69927,69995-69996,70148-70149,70347-70349,70377,70526-70527,71006-71007,71009-71022,71046-71047,71049,71096-71100,77226-77229
 /brlcad/branches/bullet:62518
 /brlcad/branches/cmake:43219
 /brlcad/branches/dm-fb-merge:75426-76198
## -9,4 +10,4 ##
 /brlcad/branches/osg:62110-62113
 /brlcad/branches/prep-cache:68236-68933
 /brlcad/branches/tcltk86:68300-75257
-/brlcad/trunk:75720-76157,76160-76365,76386-77219
\ No newline at end of property
+/brlcad/trunk:75720-76157,76160-76365,76386-77302
\ No newline at end of property
Modified: brlcad/branches/bioh/NEWS
===================================================================
--- brlcad/branches/bioh/NEWS   2020-10-01 13:13:00 UTC (rev 77302)
+++ brlcad/branches/bioh/NEWS   2020-10-01 13:15:27 UTC (rev 77303)
@@ -13,6 +13,12 @@
 --- 2020-xx-xx  Release 7.32.2                                     ---
 ----------------------------------------------------------------------
 
+* applied shorter default title in fast4-g conversions - Cliff Yapp
+* improved pixcmp support for subset image comparisons - Sean Morrison
+* added subtract subcommand to MGED analyze command - Cliff Yapp
+* added intersect subcommand to MGED analyze command - Cliff Yapp
+* added summarize subcommand to MGED analyze command - Cliff Yapp
+* added quiet (-q) flag to MGED kill command - Cliff Yapp
 * added MGED stat command for reporting of object info - Cliff Yapp
 * corrected examples in gdiff man page - Cliff Yapp
 * fixed help message for -F option on gdiff command - Cliff Yapp


Property changes on: brlcad/branches/bioh/NEWS
___________________________________________________________________
Modified: svn:mergeinfo
## -8,4 +8,4 ##
 /brlcad/branches/osg/NEWS:62110-62113
 /brlcad/branches/prep-cache/NEWS:68236-68933
 /brlcad/branches/tcltk86/NEWS:68300-75257
-/brlcad/trunk/NEWS:75728-75834,75934-76085,76134-76146,76148-76154,76160-76351,76386-76505,76569-76653,76685-76859,76862-77219
\ No newline at end of property
+/brlcad/trunk/NEWS:75728-75834,75934-76085,76134-76146,76148-76154,76160-76351,76386-76505,76569-76653,76685-76859,76862-77302
\ No newline at end of property
Modified: brlcad/branches/bioh/TODO
===================================================================
--- brlcad/branches/bioh/TODO   2020-10-01 13:13:00 UTC (rev 77302)
+++ brlcad/branches/bioh/TODO   2020-10-01 13:15:27 UTC (rev 77303)
@@ -18,12 +18,9 @@
 THESE TASKS SHOULD HAPPEN BEFORE THE NEXT RELEASE
 -------------------------------------------------
 
-* Release Testing, final commit reviews
+* Update libgcv plugin installation location - now that its
+  available, they belong with the other plugins in libexec
 
-
-THESE TASKS SHOULD HAPPEN WITHIN TWO RELEASE ITERATIONS
--------------------------------------------------------
-
 * The following will be removed from MGED's menu bar (unused
   features, can be accomplished another way, or will be exposed
   only as lower level settings when there are sensible defaults
@@ -169,6 +166,11 @@
   allocation, not just do some work
 
 
+THESE TASKS SHOULD HAPPEN WITHIN TWO RELEASE ITERATIONS
+-------------------------------------------------------
+
+
+
 THESE ARE UNSCHEDULED BACKLOG TASKS
 -----------------------------------
 

Index: brlcad/branches/bioh/bench
===================================================================
--- brlcad/branches/bioh/bench  2020-10-01 13:13:00 UTC (rev 77302)
+++ brlcad/branches/bioh/bench  2020-10-01 13:15:27 UTC (rev 77303)

Property changes on: brlcad/branches/bioh/bench
___________________________________________________________________
Modified: svn:mergeinfo
## -8,4 +8,4 ##
 /brlcad/branches/osg/bench:62110-62113
 /brlcad/branches/prep-cache/bench:68236-68933
 /brlcad/branches/tcltk86/bench:68300-75257
-/brlcad/trunk/bench:75728-75834,75986-76085,76160-76351,76685-76859,77084-77219
\ No newline at end of property
+/brlcad/trunk/bench:75728-75834,75986-76085,76160-76351,76685-76859,77084-77302
\ No newline at end of property
Modified: brlcad/branches/bioh/bench/pixcmp.c
===================================================================
--- brlcad/branches/bioh/bench/pixcmp.c 2020-10-01 13:13:00 UTC (rev 77302)
+++ brlcad/branches/bioh/bench/pixcmp.c 2020-10-01 13:15:27 UTC (rev 77303)
@@ -121,7 +121,8 @@
 {
     FILE *f1 = NULL;
     FILE *f2 = NULL;
-    struct stat sf1, sf2;
+    struct stat sf1 = {0};
+    struct stat sf2 = {0};
 
     size_t matching = 0;
     size_t off1 = 0;
@@ -190,6 +191,10 @@
     }
 
     /* printf("Skip from FILE1: %ld and from FILE2: %ld\n", f1_skip, f2_skip); 
*/
+    if (!print_bytes) {
+       f1_skip *= 3;
+       f2_skip *= 3;
+    }
 
     if (BU_STR_EQUAL(argv[0], "-")) {
        f1 = stdin;
@@ -204,18 +209,25 @@
        exit(FILE_ERROR);
     }
 
-    stat(argv[0], &sf1);
-    stat(argv[1], &sf2);
+    fstat(fileno(f1), &sf1);
+    fstat(fileno(f2), &sf2);
 
-    if (sf1.st_size != sf2.st_size) {
-       bu_exit(FILE_ERROR, "Different file sizes found: %s(%d) and %s(%d).  
Cannot perform pixcmp.\n", argv[0], (int)sf1.st_size, argv[1], 
(int)sf2.st_size);
+    if ((sf1.st_size - f1_skip) != (sf2.st_size - f2_skip)) {
+       bu_log("WARNING: Different image sizes detected\n");
+       if (print_bytes) {
+           bu_log("\t%s: %7zu bytes (%8zu bytes, skipping %7zu)\n",
+                  argv[0], sf1.st_size - f1_skip, sf1.st_size, f1_skip);
+           bu_log("\t%s: %7zu bytes (%8zu bytes, skipping %7zu)\n",
+                  argv[1], sf2.st_size - f2_skip, sf2.st_size, f2_skip);
+       } else {
+           bu_log("\t%s: %7zu pixels (%8zu bytes, skipping %7zu)\n",
+                  argv[0], (sf1.st_size - f1_skip)/3, sf1.st_size, f1_skip);
+           bu_log("\t%s: %7zu pixels (%8zu bytes, skipping %7zu)\n",
+                  argv[1], (sf2.st_size - f2_skip)/3, sf2.st_size, f2_skip);
+       }
+       bu_exit(1, "ERROR: Cannot pixcmp due to different images sizes 
(unimplemented).\n");
     }
 
-    if (!print_bytes) {
-       f1_skip *= 3;
-       f2_skip *= 3;
-    }
-
     /* skip requested pixels/bytes in FILE1 */
     if (f1_skip && fseek(f1, f1_skip, SEEK_SET)) {
        bu_log("ERROR: Unable to seek %zd %s%s in FILE1\n",

Modified: brlcad/branches/bioh/bench/run.sh
===================================================================
--- brlcad/branches/bioh/bench/run.sh   2020-10-01 13:13:00 UTC (rev 77302)
+++ brlcad/branches/bioh/bench/run.sh   2020-10-01 13:15:27 UTC (rev 77303)
@@ -613,18 +613,14 @@
 fi
 
 # sanity check: make sure $CMP runs
-echo "" > tmp1
-echo "" > tmp2
-out=`echo "" | eval \"$CMP\" tmp1 tmp2 2>&1`
+out=`echo "" | eval \"$CMP\" - - 2>&1`
 ret=$?
 if test ! "x${ret}" = "x0" ; then
     $ECHO
     $ECHO "ERROR:  CMP does not seem to work as expected"
     $ECHO "        (output was [$out])"
-    rm -f tmp1 tmp2
     exit 2
 fi
-rm -f tmp1 tmp2
 
 # sanity check: make sure $ELP runs
 out=`eval \"$ELP\" 0 2>&1`

Index: brlcad/branches/bioh/doc
===================================================================
--- brlcad/branches/bioh/doc    2020-10-01 13:13:00 UTC (rev 77302)
+++ brlcad/branches/bioh/doc    2020-10-01 13:15:27 UTC (rev 77303)

Property changes on: brlcad/branches/bioh/doc
___________________________________________________________________
Modified: svn:mergeinfo
## -1,5 +1,5 ##
 
/brlcad/branches/RELEASE/doc:57439,57447-57860,69901-69913,71917-72242,72525-72534,72826-72858,74376-74454,74964-75140,77145-77155
-/brlcad/branches/brep-debug/doc:61373,61375,61404,61427,61429,61470,61544,61567,61576,61999,62018,62094,62098,62107,62117,62406,62416-62519,62521-62584,62593-62614,62623,62658,62660-62674,62681-62771,62876,62901,62907,62910,62925,62928,62931-63025,63027,63051,63054-63056,63069,63071-63073,63122,63160-63161,63165,63171,63184,63187,63189-63190,63193-63196,63200,63202,63205-63210,63213,63219-63225,63232-63233,63236,63238,63338,63350-63353,63481,63618,63669,64173-64174,64176-64177,64229-64233,64242,64244,64360-64362,65165,65245,65249,65334,65833-65834,66370-66375,66931-66932,66934,67012-67015,67018-67019,67021-67022,67406,67740,67746-67748,67950,67952,68144-68145,68636,68640-68643,68820,69081,69109,69206,69289,69346,69460-69461,69582-69583,69719-69721,69857-69859,69927
+/brlcad/branches/brep-debug/doc:61373,61375,61404,61427,61429,61470,61544,61567,61576,61999,62018,62094,62098,62107,62117,62406,62416-62519,62521-62584,62593-62614,62623,62658,62660-62674,62681-62771,62876,62901,62907,62910,62925,62928,62931-63025,63027,63051,63054-63056,63069,63071-63073,63122,63160-63161,63165,63171,63184,63187,63189-63190,63193-63196,63200,63202,63205-63210,63213,63219-63225,63232-63233,63236,63238,63338,63350-63353,63481,63618,63669,64173-64174,64176-64177,64229-64233,64242,64244,64360-64362,65165,65245,65249,65334,65833-65834,66370-66375,66931-66932,66934,67012-67015,67018-67019,67021-67022,67406,67740,67746-67748,67950,67952,68144-68145,68636,68640-68643,68820,69081,69109,69206,69289,69346,69460-69461,69582-69583,69719-69721,69857-69859,69927,77226-77229
 /brlcad/branches/bullet/doc:62518
 /brlcad/branches/cmake/doc:43219
 /brlcad/branches/dm-fb-merge/doc:75426-76198
## -8,4 +8,4 ##
 /brlcad/branches/osg/doc:62110-62113
 /brlcad/branches/prep-cache/doc:68236-68933
 /brlcad/branches/tcltk86/doc:68300-75257
-/brlcad/trunk/doc:75728-75834,75934-76134,76148-76154,76160-76351,76386-76505,76641-76653,76685-76859,76862-77219
\ No newline at end of property
+/brlcad/trunk/doc:75728-75834,75934-76134,76148-76154,76160-76351,76386-76505,76641-76653,76685-76859,76862-77302
\ No newline at end of property
Modified: brlcad/branches/bioh/doc/docbook/CMakeLists.txt
===================================================================
--- brlcad/branches/bioh/doc/docbook/CMakeLists.txt     2020-10-01 13:13:00 UTC 
(rev 77302)
+++ brlcad/branches/bioh/doc/docbook/CMakeLists.txt     2020-10-01 13:15:27 UTC 
(rev 77303)
@@ -36,6 +36,7 @@
 
 add_subdirectory(articles)
 add_subdirectory(books)
+add_subdirectory(devguides)
 add_subdirectory(lessons)
 add_subdirectory(presentations)
 add_subdirectory(specifications)

Modified: brlcad/branches/bioh/doc/docbook/system/mann/analyze.xml
===================================================================
--- brlcad/branches/bioh/doc/docbook/system/mann/analyze.xml    2020-10-01 
13:13:00 UTC (rev 77302)
+++ brlcad/branches/bioh/doc/docbook/system/mann/analyze.xml    2020-10-01 
13:15:27 UTC (rev 77303)
@@ -10,9 +10,7 @@
   <refnamediv xml:id="name">
     <refname>analyze</refname>
     <refpurpose>
-      Displays the rotation and fallback angles, surface area, and
-      plane equation for each face of the ARB specified on the command line. 
The total
-      surface area, volume, and the length of each edge are also displayed.
+      Report and/or compute analytical information about the listed objects.
     </refpurpose>
   </refnamediv>
 
@@ -20,39 +18,243 @@
   <refsynopsisdiv xml:id="synopsis">
     <cmdsynopsis sepchar=" ">
       <command>analyze</command>
-      <arg choice="req" 
rep="norepeat"><replaceable>arb_name</replaceable></arg>
+      <arg choice="opt" rep="repeat"><replaceable>options</replaceable></arg>
+      <arg choice="opt" 
rep="norepeat"><replaceable>subcommand</replaceable></arg>
     </cmdsynopsis>
+    <variablelist>
+      
+      <varlistentry><term></term><listitem>
+      <cmdsynopsis sepchar=" ">
+       <command>summarize</command>
+       <arg choice="req" rep="repeat">obj</arg>
+      </cmdsynopsis>
+      </listitem></varlistentry>
+      
+      <varlistentry><term></term><listitem>
+      <cmdsynopsis sepchar=" ">
+       <command>intersect</command>
+       <arg choice="opt" rep="repeat"><replaceable>options</replaceable></arg>
+       <arg choice="req" rep="repeat">obj1 obj2 [...]</arg>
+      </cmdsynopsis>
+      </listitem></varlistentry>
+      
+      <varlistentry><term></term><listitem>
+      <cmdsynopsis sepchar=" ">
+       <command>subtract</command>
+       <arg choice="opt" rep="repeat"><replaceable>options</replaceable></arg>
+       <arg choice="req" rep="repeat">obj1 obj2 [...]</arg>
+      </cmdsynopsis>
+      </listitem></varlistentry>
+    </variablelist>
   </refsynopsisdiv>
 
   <refsection xml:id="description"><title>DESCRIPTION</title>
 
     <para>
-      The <command>analyze</command> command displays the rotation and fallback
-      angles, surface area, and plane equation for each face of the ARB 
specified
-      on the command line. The total surface area, volume, and the length of 
each
-      edge are also displayed. If executed while editing an ARB, the arb_name 
may
-      be omitted, and the ARB being edited will be analyzed.
+      The <command>analyze</command> command provides an array of reporting and
+      shape generation capabilities.  The classic behavior (and the behavior 
users
+      will see if calling without specifying a subcommand) is a report 
summarizing
+      geometric information about the specified solid(s).  This behavior may 
also
+      be explicitly invoked by the <command>summarize</command> subcommand.
     </para>
+
+    <para>
+      The <command>intersect</command> will take the first object specified and
+      intersect it with any subsequently specified objects - in effect, 
building
+      up a new object with the geoemtry common to all objects specified.
+    </para>
+
+    <para>
+      The <command>subtract</command> will take the first object specified and
+      subtract from it any subsequently specified objects.
+    </para>
+    
   </refsection>
 
   <refsection xml:id="examples"><title>EXAMPLES</title>
 
-    <para>
-      The example shows how to display information about an ARB's rotation and
-      fallback angles, surface area, and plane equation for its face.
-      Edge information is also displayed.
-    </para>
     <example><title>Analyze a particular <emphasis>ARB</emphasis></title>
+      <para>
+       <prompt>mged&gt;</prompt> <userinput>analyze box.s</userinput>
+      </para>
+      <literallayout>
+box.s:  ARB8
+       1 (30.0283, -5.21153, -16.3791)
+       2 (30.0283, 21.5812, -16.3791)
+       3 (30.0283, 21.5812, 10.4137)
+       4 (30.0283, -5.21153, 10.4137)
+       5 (3.23558, -5.21153, -16.3791)
+       6 (3.23558, 21.5812, -16.3791)
+       7 (3.23558, 21.5812, 10.4137)
+       8 (3.23558, -5.21153, 10.4137)
 
++------+---------------------------+-------------------------------------------------+--------------+
+| FACE |     ROT          FB       |                 PLANE EQUATION            
      | SURFACE AREA |
++------+---------------------------+-------------------------------------------------+--------------+
+| 1234 |   0.00000000   0.00000000 |  1.00000000  0.00000000  0.00000000 
30.02833557 | 717.85172729 |
+| 5678 | 180.00000000  -0.00000000 | -1.00000000 -0.00000000 -0.00000000 
-3.23558044 | 717.85172729 |
+| 1584 | 270.00000000  -0.00000000 | -0.00000000 -1.00000000 -0.00000000  
5.21152973 | 717.85172729 |
+| 2376 |  90.00000000  -0.00000000 | -0.00000000  1.00000000 -0.00000000 
21.58122540 | 717.85172729 |
+| 1265 |   0.00000000 -90.00000000 | -0.00000000  0.00000000 -1.00000000 
16.37908936 | 717.85172729 |
+| 4378 |   0.00000000  90.00000000 |  0.00000000 -0.00000000  1.00000000 
10.41366577 | 717.85172729 |
++------+---------------------------+-------------------------------------------------+--------------+
+
+  
+--------------------+--------------------+--------------------+--------------------+
+  | EDGE        LENGTH | EDGE        LENGTH | EDGE        LENGTH | EDGE        
LENGTH |
+  
+--------------------+--------------------+--------------------+--------------------+
+  | 12     26.79275513 | 23     26.79275513 | 34     26.79275513 | 14     
26.79275513 |
+  | 15     26.79275513 | 56     26.79275513 | 26     26.79275513 | 67     
26.79275513 |
+  | 78     26.79275513 | 58     26.79275513 | 48     26.79275513 | 37     
26.79275513 |
+  
+--------------------+--------------------+--------------------+--------------------+
+
+    +-------------------------------+
+    | Volume       = 19233.22554681 |
+    | Surface Area =  4307.11036376 |
+    | Gallons      =     0.00508088 |
+    +-------------------------------+
+      </literallayout>
+    </example>
+
+     <example><title>Analyze a particular <emphasis>TOR</emphasis></title>
       <para>
-       <prompt>mged&gt;</prompt> <userinput>analyze arb_name</userinput>
+       <prompt>mged&gt;</prompt> <userinput>analyze tor</userinput>
       </para>
+      <literallayout>
+tor:  torus (TOR)
+       V (4.91624, -32.8022, 31.7118), r1=25.4 (A), r2=5.08 (H)
+       N=(0, 1, 0)
+       A=(0, -0, 1)
+       B=(1, 0, -0)
+       vector to inner edge = (0, -0, 20.32)
+       vector to outer edge = (0, -0, 30.48)
+
+    Centroid: (4.91624, -32.8022, 31.7118)
+
+    +-------------------------------+
+    | Volume       = 12938.70529707 |
+    | Surface Area =  5093.97853992 |
+    | Gallons      =     0.00341804 |
+    +-------------------------------+
+      </literallayout>
+    </example>
+    
+    <example><title>Points inside a sphere</title>
+    
       <para>
-       Rotation and fallback angles, surface area, and plane equation for
-       each face of the ARB specified on the command line are displayed along
-       with edge information.
+       <prompt>mged&gt;</prompt> <userinput>l sph.s</userinput>
       </para>
+      <literallayout>
+sph.s:  ellipsoid (ELL)
+       V (0, 0, 0)
+       A (10, 0, 0) mag=10
+       B (0, 10, 0) mag=10
+       C (0, 0, 10) mag=10
+       A direction cosines=(0, 90, 90)
+       A rotation angle=0, fallback angle=0
+       B direction cosines=(90, 0, 90)
+       B rotation angle=90, fallback angle=0
+       C direction cosines=(90, 90, 0)
+       C rotation angle=0, fallback angle=90
+      </literallayout>
+      
+      <para>
+       <prompt>mged&gt;</prompt> <userinput>l pnts.s</userinput>
+      </para>
+      <literallayout>
+pnts.s:  Point Cloud (PNTS)
+Total number of points: 6
+Default scale: 0.000000
+point#, (point)
+1,      (2.000000 2.000000 2.000000)
+2,      (0.000000 0.000000 -5.000000)
+3,      (0.000000 0.000000 10.000000)
+4,      (0.000000 0.000000 20.000000)
+5,      (10.000000 0.000000 10.000000)
+6,      (0.000000 10.000000 20.000000)
+      </literallayout>
+      
+      <para>
+       <prompt>mged&gt;</prompt> <userinput>analyze intersect -o inside.s 
pnts.s sph.s</userinput>
+      </para>
+      <literallayout>
+3
+      </literallayout>
+      
+      <para>
+       <prompt>mged&gt;</prompt> <userinput>l inside.s</userinput>
+      </para>
+      <literallayout>
+inside.s:  Point Cloud (PNTS)
+Total number of points: 3
+Default scale: 0.000000
+point#, (point)
+1,      (0.000000 0.000000 10.000000)
+2,      (0.000000 0.000000 -5.000000)
+3,      (2.000000 2.000000 2.000000)
+      </literallayout>
+
     </example>
+
+
+    <example><title>Points outside a sphere</title>
+    
+      <para>
+       <prompt>mged&gt;</prompt> <userinput>l sph.s</userinput>
+      </para>
+      <literallayout>
+sph.s:  ellipsoid (ELL)
+       V (0, 0, 0)
+       A (10, 0, 0) mag=10
+       B (0, 10, 0) mag=10
+       C (0, 0, 10) mag=10
+       A direction cosines=(0, 90, 90)
+       A rotation angle=0, fallback angle=0
+       B direction cosines=(90, 0, 90)
+       B rotation angle=90, fallback angle=0
+       C direction cosines=(90, 90, 0)
+       C rotation angle=0, fallback angle=90
+      </literallayout>
+      
+      <para>
+       <prompt>mged&gt;</prompt> <userinput>l pnts.s</userinput>
+      </para>
+      <literallayout>
+pnts.s:  Point Cloud (PNTS)
+Total number of points: 6
+Default scale: 0.000000
+point#, (point)
+1,      (2.000000 2.000000 2.000000)
+2,      (0.000000 0.000000 -5.000000)
+3,      (0.000000 0.000000 10.000000)
+4,      (0.000000 0.000000 20.000000)
+5,      (10.000000 0.000000 10.000000)
+6,      (0.000000 10.000000 20.000000)
+      </literallayout>
+      
+      <para>
+       <prompt>mged&gt;</prompt> <userinput>analyze subtract -o outside.s 
pnts.s sph</userinput>
+      </para>
+      <literallayout>
+3
+      </literallayout>
+
+      <para>
+       <prompt>mged&gt;</prompt> <userinput>l outside.s</userinput>
+      </para>
+      <literallayout>
+outside.s:  Point Cloud (PNTS)
+Total number of points: 3
+Default scale: 0.000000
+point#, (point)
+1,      (0.000000 10.000000 20.000000)
+2,      (10.000000 0.000000 10.000000)
+3,      (0.000000 0.000000 20.000000)
+      </literallayout>
+
+      
+    </example>
+
+    
   </refsection>
 
   <refsection xml:id="author"><title>AUTHOR</title>

Modified: brlcad/branches/bioh/doc/docbook/system/mann/kill.xml
===================================================================
--- brlcad/branches/bioh/doc/docbook/system/mann/kill.xml       2020-10-01 
13:13:00 UTC (rev 77302)
+++ brlcad/branches/bioh/doc/docbook/system/mann/kill.xml       2020-10-01 
13:15:27 UTC (rev 77303)
@@ -1,61 +1,79 @@
 <refentry xmlns="http://docbook.org/ns/docbook"; version="5.0" xml:id="kill">
 
-<refmeta>
-  <refentrytitle>KILL</refentrytitle>
-  <manvolnum>nged</manvolnum>
-  <refmiscinfo class="source">BRL-CAD</refmiscinfo>
-  <refmiscinfo class="manual">BRL-CAD User Commands</refmiscinfo>
-</refmeta>
+  <refmeta>
+    <refentrytitle>KILL</refentrytitle>
+    <manvolnum>nged</manvolnum>
+    <refmiscinfo class="source">BRL-CAD</refmiscinfo>
+    <refmiscinfo class="manual">BRL-CAD User Commands</refmiscinfo>
+  </refmeta>
 
-<refnamediv xml:id="name">
-  <refname>kill</refname>
-  <refpurpose>Deletes specified <emphasis>objects</emphasis> from the current 
database.
-   </refpurpose>
-</refnamediv>
+  <refnamediv xml:id="name">
+    <refname>kill</refname>
+    <refpurpose>Deletes specified <emphasis>objects</emphasis> from the 
current database.
+    </refpurpose>
+  </refnamediv>
 
-<!-- body begins here -->
-<refsynopsisdiv xml:id="synopsis">
-  <cmdsynopsis sepchar=" ">
-    <command>kill</command>
-     <arg choice="opt" rep="norepeat">-f</arg>
-     <arg choice="req" rep="norepeat"><replaceable>objects</replaceable></arg>
-  </cmdsynopsis>
-</refsynopsisdiv>
+  <!-- body begins here -->
+  <refsynopsisdiv xml:id="synopsis">
+    <cmdsynopsis sepchar=" ">
+      <command>kill</command>
+      <arg choice="opt" rep="norepeat">-f</arg>
+      <arg choice="req" rep="norepeat"><replaceable>objects</replaceable></arg>
+    </cmdsynopsis>
+  </refsynopsisdiv>
 
-<refsection xml:id="description"><title>DESCRIPTION</title>
+  <refsection xml:id="description"><title>DESCRIPTION</title>
 
   <para>
-    Deletes the specified <emphasis>objects</emphasis> from the current 
database.
-       This command affects only the <emphasis>objects</emphasis> actually 
listed on the command       line. If a combination is killed, its members are 
not affected. If the <emphasis>-f     </emphasis>option is specified, then kill 
will not complain if some, or all, of the     <emphasis>objects</emphasis> 
specified do not actually exist in the database. Note that         the 
<emphasis>objects</emphasis> are killed immediately. There is no need for a 
<command>       write file</command> command in MGED, and there is no 
<command>undo</command> command.  <emphasis remap="B" role="bold">Use this 
command with caution.</emphasis> Other commands        that remove objects from 
the database are <command>killall</command> and <command>killtree      
</command>.
+    Deletes the specified <emphasis>objects</emphasis> from the current 
database.  This command
+    affects only the <emphasis>objects</emphasis> actually listed on the 
command line. If a
+    combination is killed, its members are not affected. If the 
<emphasis>-f</emphasis>option
+    is specified, then kill will not complain if some, or all, of the 
<emphasis>objects</emphasis>
+    specified do not actually exist in the database. Note that         the 
<emphasis>objects</emphasis>
+    are killed immediately. There is no need for a <command>write 
file</command> command in MGED,
+    and there is no <command>undo</command> command. <emphasis remap="B" 
role="bold">Use this
+    command with caution.</emphasis> Other commands that remove objects from 
the database are
+    <command>killall</command> and <command>killtree</command>.
   </para>
-</refsection>
+  <para>
+    The <option>-q</option> option may be added to suppress database object 
lookup messages
+    reporting failure, which will otherwise let the user know an invalid 
object was specified.
+  </para>
+  </refsection>
 
-<refsection xml:id="examples"><title>EXAMPLES</title>
-
-  <para>The example shows the use of the <command>kill</command> command to 
delete specified   objects from the database.
+  <refsection xml:id="examples"><title>EXAMPLES</title>
+  <para>
+    The example shows the use of the <command>kill</command> command to delete 
specified objects
+    from the database.
   </para>
   <example><title>Delete objects from the database.</title>
 
-    <variablelist>
-      <varlistentry>
-          <term><prompt>mged&gt;</prompt> <userinput>kill group1 region2 
shapeb</userinput></term>
-          <listitem>
-            <para>Deletes <emphasis>group1, region2</emphasis>, and 
<emphasis>shapeb</emphasis>                                from the database.
-             </para>
-          </listitem>
-      </varlistentry>
-    </variablelist>
+  <variablelist>
+    <varlistentry>
+      <term><prompt>mged&gt;</prompt> <userinput>kill group1 region2 
shapeb</userinput></term>
+      <listitem>
+       <para>
+         Deletes <emphasis>group1, region2</emphasis>, and 
<emphasis>shapeb</emphasis> from
+         the database.
+       </para>
+      </listitem>
+    </varlistentry>
+  </variablelist>
   </example>
 
-</refsection>
+  </refsection>
 
-<refsection xml:id="author"><title>AUTHOR</title><para>BRL-CAD 
Team</para></refsection>
+  <refsection xml:id="author"><title>AUTHOR</title>
+  <para>
+    BRL-CAD Team
+  </para>
+  </refsection>
 
-<refsection xml:id="bug_reports"><title>BUG REPORTS</title>
+  <refsection xml:id="bug_reports"><title>BUG REPORTS</title>
 
   <para>
     Reports of bugs or problems should be submitted via electronic
     mail to <email>[email protected]</email>
   </para>
-</refsection>
+  </refsection>
 </refentry>

Modified: brlcad/branches/bioh/doc/legal/embedded/SPSR.txt
===================================================================
--- brlcad/branches/bioh/doc/legal/embedded/SPSR.txt    2020-10-01 13:13:00 UTC 
(rev 77302)
+++ brlcad/branches/bioh/doc/legal/embedded/SPSR.txt    2020-10-01 13:15:27 UTC 
(rev 77303)
@@ -48,6 +48,42 @@
 ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
 POSSIBILITY OF SUCH DAMAGE.
 
+
+Uses PlyVertexMini.h from geogram:
+https://github.com/alicevision/geogram/blob/master/src/lib/geogram/third_party/PoissonRecon/PlyVertexMini.h
+
+Geogram is licensed under the 3-clauses BSD License (also called "Revised
+BSD License", "New BSD License", or "Modified BSD License"):
+
+Copyright (c) 2012-2014, Bruno Levy All rights reserved.
+
+Redistribution and use in source and binary forms, with or without
+modification, are permitted provided that the following conditions are met:
+
+Redistributions of source code must retain the above copyright notice, this
+list of conditions and the following disclaimer. Redistributions in binary
+form must reproduce the above copyright notice, this list of conditions and
+the following disclaimer in the documentation and/or other materials
+provided with the distribution. Neither the name of the ALICE Project-Team
+nor the names of its contributors may be used to endorse or promote products
+derived from this software without specific prior written permission.
+
+THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
+AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
+IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
+ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE
+LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
+CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
+SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
+INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
+CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
+ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
+POSSIBILITY OF SUCH DAMAGE.
+
+If you modify this software, you should include a notice giving the name of
+the person performing the modification, the date of modification, and the
+reason for such modification.
+
 file:/include/bg/spsr.h
 file:/src/other/libspsr/Src/Allocator.h
 file:/src/other/libspsr/Src/Array.h
@@ -80,8 +116,7 @@
 file:/src/other/libspsr/Src/Octree.inl
 file:/src/other/libspsr/Src/PPolynomial.h
 file:/src/other/libspsr/Src/PPolynomial.inl
-file:/src/other/libspsr/Src/Ply.h
-file:/src/other/libspsr/Src/PlyFile.cpp
+file:/src/other/libspsr/Src/PlyVertexMini.h
 file:/src/other/libspsr/Src/PointStream.h
 file:/src/other/libspsr/Src/PointStream.inl
 file:/src/other/libspsr/Src/PoissonRecon.cpp

Modified: brlcad/branches/bioh/doc/legal/other/CMakeLists.txt
===================================================================
--- brlcad/branches/bioh/doc/legal/other/CMakeLists.txt 2020-10-01 13:13:00 UTC 
(rev 77302)
+++ brlcad/branches/bioh/doc/legal/other/CMakeLists.txt 2020-10-01 13:15:27 UTC 
(rev 77303)
@@ -16,7 +16,6 @@
   openscenegraph.txt
   poly2tri.txt
   proj-4.txt
-  SPSR.txt
   stepcode.txt
   tcl.txt
   tkhtml.txt

Deleted: brlcad/branches/bioh/doc/legal/other/SPSR.txt
===================================================================
--- brlcad/branches/bioh/doc/legal/other/SPSR.txt       2020-10-01 13:13:00 UTC 
(rev 77302)
+++ brlcad/branches/bioh/doc/legal/other/SPSR.txt       2020-10-01 13:15:27 UTC 
(rev 77303)
@@ -1,25 +0,0 @@
-Copyright (c) 2006, Michael Kazhdan and Matthew Bolitho
-All rights reserved.
-
-Redistribution and use in source and binary forms, with or without 
modification,
-are permitted provided that the following conditions are met:
-
-Redistributions of source code must retain the above copyright notice, this 
list of
-conditions and the following disclaimer. Redistributions in binary form must 
reproduce
-the above copyright notice, this list of conditions and the following 
disclaimer
-in the documentation and/or other materials provided with the distribution.
-
-Neither the name of the Johns Hopkins University nor the names of its 
contributors
-may be used to endorse or promote products derived from this software without 
specific
-prior written permission.
-
-THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" 
AND ANY
-EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO THE IMPLIED 
WARRANTIES
-OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO 
EVENT
-SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT,
-INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT 
LIMITED
-TO, PROCUREMENT OF SUBSTITUTE  GOODS OR SERVICES; LOSS OF USE, DATA, OR 
PROFITS; OR
-BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER 
IN
-CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) 
ARISING IN
-ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF 
SUCH
-DAMAGE.

Index: brlcad/branches/bioh/include
===================================================================
--- brlcad/branches/bioh/include        2020-10-01 13:13:00 UTC (rev 77302)
+++ brlcad/branches/bioh/include        2020-10-01 13:15:27 UTC (rev 77303)

Property changes on: brlcad/branches/bioh/include
___________________________________________________________________
Modified: svn:mergeinfo
## -1,5 +1,5 ##
 
/brlcad/branches/RELEASE/include:57439,57447-57860,69901-69913,71915-72242,72525-72534,72826-72858,74376-74454,74964-75140,75372-75681,76726-76768
-/brlcad/branches/brep-debug/include:61373,61375,61404,61427,61429,61470,61544,61567,61576,61999,62018,62094,62098,62107,62117,62406,62416-62519,62521-62584,62593-62614,62623,62658,62660-62674,62681-62771,62876,62901,62907,62910,62925,62928,62931-63025,63027,63051,63054-63056,63069,63071-63073,63122,63160-63161,63165,63171,63184,63187,63189-63190,63193-63196,63200,63202,63205-63210,63213,63219-63225,63232-63233,63236,63238,63338,63350-63353,63481,63618,63669,64173-64174,64176-64177,64229-64233,64242,64244,64360-64362,65165,65245,65249,65334,65833-65834,66370-66375,66931-66932,66934,67012-67015,67018-67019,67021-67022,67406,67740,67746-67748,67950,67952,68144-68145,68636,68640-68643,68820,69081,69109,69206,69289,69346,69460-69461,69582-69583,69719-69721,69857-69859,69927
+/brlcad/branches/brep-debug/include:61373,61375,61404,61427,61429,61470,61544,61567,61576,61999,62018,62094,62098,62107,62117,62406,62416-62519,62521-62584,62593-62614,62623,62658,62660-62674,62681-62771,62876,62901,62907,62910,62925,62928,62931-63025,63027,63051,63054-63056,63069,63071-63073,63122,63160-63161,63165,63171,63184,63187,63189-63190,63193-63196,63200,63202,63205-63210,63213,63219-63225,63232-63233,63236,63238,63338,63350-63353,63481,63618,63669,64173-64174,64176-64177,64229-64233,64242,64244,64360-64362,65165,65245,65249,65334,65833-65834,66370-66375,66931-66932,66934,67012-67015,67018-67019,67021-67022,67406,67740,67746-67748,67950,67952,68144-68145,68636,68640-68643,68820,69081,69109,69206,69289,69346,69460-69461,69582-69583,69719-69721,69857-69859,69927,77226-77229
 /brlcad/branches/bullet/include:62518
 /brlcad/branches/cmake/include:43219
 /brlcad/branches/dm-fb-merge/include:75426-76198
## -9,4 +9,4 ##
 /brlcad/branches/osg/include:62110-62113
 /brlcad/branches/prep-cache/include:68236-68933
 /brlcad/branches/tcltk86/include:68300-75257
-/brlcad/trunk/include:75728-75834,75891-75926,75986-76146,76148-76154,76160-76351,76386-76505,76641-76859,76862-77219
\ No newline at end of property
+/brlcad/trunk/include:75728-75834,75891-75926,75986-76146,76148-76154,76160-76351,76386-76505,76641-76859,76862-77302
\ No newline at end of property
Modified: brlcad/branches/bioh/include/ged/commands.h
===================================================================
--- brlcad/branches/bioh/include/ged/commands.h 2020-10-01 13:13:00 UTC (rev 
77302)
+++ brlcad/branches/bioh/include/ged/commands.h 2020-10-01 13:15:27 UTC (rev 
77303)
@@ -860,6 +860,11 @@
  */
 GED_EXPORT extern int ged_stat(struct ged *gedp, int argc, const char *argv[]);
 
+
+
+/* Debugging command for brep plotting */
+GED_EXPORT extern int ged_dplot(struct ged *gedp, int argc, const char 
*argv[]);
+
 /** @} */
 
 

Modified: brlcad/branches/bioh/src/conv/fast4-g.c
===================================================================
--- brlcad/branches/bioh/src/conv/fast4-g.c     2020-10-01 13:13:00 UTC (rev 
77302)
+++ brlcad/branches/bioh/src/conv/fast4-g.c     2020-10-01 13:15:27 UTC (rev 
77303)
@@ -38,6 +38,7 @@
 #include "bu/app.h"
 #include "bu/debug.h"
 #include "bu/getopt.h"
+#include "bu/path.h"
 #include "rt/db4.h"
 #include "vmath.h"
 #include "nmg.h"
@@ -2839,8 +2840,12 @@
     rewind(fpin);
 
     /* Make an ID record if no vehicle card was found */
-    if (!vehicle[0])
-       mk_id_units(fpout, argv[bu_optind], "in");
+    if (!vehicle[0]) {
+       struct bu_vls fname = BU_VLS_INIT_ZERO;
+       bu_path_component(&fname, argv[bu_optind], BU_PATH_BASENAME);
+       mk_id_units(fpout, bu_vls_cstr(&fname), "in");
+       bu_vls_free(&fname);
+    }
 
     if (!quiet)
        bu_log("Building components....\n");

Modified: brlcad/branches/bioh/src/libbrep/CMakeLists.txt
===================================================================
--- brlcad/branches/bioh/src/libbrep/CMakeLists.txt     2020-10-01 13:13:00 UTC 
(rev 77302)
+++ brlcad/branches/bioh/src/libbrep/CMakeLists.txt     2020-10-01 13:15:27 UTC 
(rev 77303)
@@ -33,6 +33,7 @@
   cdt/mesh.cpp
   cdt/ovlps_simple.cpp
   cdt/tri_isect.cpp
+  debug_plot.cpp
   intersect.cpp
   tools/tools.cpp
   opennurbs_ext.cpp

Modified: brlcad/branches/bioh/src/libbrep/boolean.cpp
===================================================================
--- brlcad/branches/bioh/src/libbrep/boolean.cpp        2020-10-01 13:13:00 UTC 
(rev 77302)
+++ brlcad/branches/bioh/src/libbrep/boolean.cpp        2020-10-01 13:15:27 UTC 
(rev 77303)
@@ -21,6 +21,8 @@
  *
  * Evaluate NURBS booleans (union, intersection and difference).
  *
+ * Additional documentation can be found in the "NURBS Boolean Evaluation
+ * Development Guide" docbook article (bool_eval_development.html).
  */
 
 #include "common.h"
@@ -31,6 +33,7 @@
 #include <queue>
 #include <set>
 #include <map>
+#include <sstream>
 
 #include "bio.h"
 
@@ -43,21 +46,16 @@
 #include "brep/ray.h"
 #include "brep/util.h"
 
+#include "debug_plot.h"
 #include "brep_except.h"
+#include "brep_defines.h"
 
+DebugPlot *dplot = NULL;
 
 // Whether to output the debug messages about b-rep booleans.
 #define DEBUG_BREP_BOOLEAN 0
 
-// tol value used in ON_Intersect()s. We use a smaller tolerance than the
-// default one 0.001.
-#define INTERSECTION_TOL 1e-4
 
-// tol value used in ON_3dVector::IsParallelTo(). We use a smaller tolerance
-// than the default one ON_PI/180.
-#define ANGLE_TOL ON_PI/1800.0
-
-
 struct IntersectPoint {
     ON_3dPoint m_pt;   // 3D intersection point
     double m_seg_t;    // param on the loop curve
@@ -104,7 +102,7 @@
 };
 
 
-HIDDEN void
+void
 append_to_polycurve(ON_Curve *curve, ON_PolyCurve &polycurve);
 // We link the SSICurves that share an endpoint, and form this new structure,
 // which has many similar behaviors as ON_Curve, e.g. PointAt(), Reverse().
@@ -344,7 +342,7 @@
 }
 
 
-HIDDEN void
+void
 append_to_polycurve(ON_Curve *curve, ON_PolyCurve &polycurve)
 {
     // use this function rather than ON_PolyCurve::Append() to avoid
@@ -3445,7 +3443,7 @@
        std::set<int> *unused = i < face_count1 ? &unused1 : &unused2;
        std::set<int> *intact = i < face_count1 ? &finalform1 : &finalform2;
        int curr_index = i < face_count1 ? i : i - face_count1;
-       if (face.BoundingBox().MinimumDistanceTo(brep->BoundingBox()) > 
ON_ZERO_TOLERANCE) {
+       if (face.BoundingBox().MinimumDistanceTo(brep->BoundingBox()) > 
INTERSECTION_TOL) {
            switch (operation) {
                case BOOLEAN_UNION:
                    intact->insert(curr_index);
@@ -3483,8 +3481,8 @@
                if (unused2.find(j) == unused2.end() &&  finalform2.find(j) == 
finalform2.end()) {
                    // If the two faces don't interact according to their 
bounding boxes,
                    // they won't be a source of events - otherwise, they must 
be checked.
-                   fastf_t disjoint = 
brep1->m_F[i].BoundingBox().MinimumDistanceTo(brep2->m_F[j].BoundingBox());
-                   if (!(disjoint > ON_ZERO_TOLERANCE)) {
+                   fastf_t face_dist = 
brep1->m_F[i].BoundingBox().MinimumDistanceTo(brep2->m_F[j].BoundingBox());
+                   if (face_dist <= INTERSECTION_TOL) {
                        intersection_candidates.insert(std::pair<int, int>(i, 
j));
                    }
                }
@@ -3563,6 +3561,10 @@
                if (results <= 0) {
                    continue;
                }
+
+               dplot->SSX(events, brep1, brep1->m_F[i].m_si, brep2, 
brep2->m_F[j].m_si);
+               dplot->WriteLog();
+
                ON_SimpleArray<ON_Curve *> face1_curves, face2_curves;
                for (int k = 0; k < events.Count(); k++) {
                    if (events[k].m_type == ON_SSX_EVENT::ssx_tangent ||
@@ -3590,6 +3592,8 @@
                        }
                    }
                }
+               dplot->ClippedFaceCurves(surf1, surf2, face1_curves, 
face2_curves);
+               dplot->WriteLog();
 
                if (DEBUG_BREP_BOOLEAN) {
                    // Look for coplanar faces
@@ -3603,7 +3607,6 @@
                }
 
            }
-
        }
     }
 
@@ -3694,6 +3697,7 @@
            }
 
            splitted[j]->m_rev = false;
+           splitted[j]->m_belong_to_final = TrimmedFace::NOT_BELONG;
            switch (face_location) {
                case INSIDE_BREP:
                    if (operation == BOOLEAN_INTERSECT ||
@@ -3798,6 +3802,8 @@
     for (int i = 0; i < original_faces.Count(); i++) {
        TrimmedFace *first = original_faces[i];
        ON_ClassArray<LinkedCurve> linked_curves = link_curves(curves_array[i]);
+       dplot->LinkedCurves(first->m_face->SurfaceOf(), linked_curves);
+       dplot->WriteLog();
 
        ON_SimpleArray<TrimmedFace *> splitted = split_trimmed_face(first, 
linked_curves);
        trimmed_faces.Append(splitted);
@@ -3826,6 +3832,9 @@
 
     categorize_trimmed_faces(trimmed_faces, brep1, brep2, surf_tree1, 
surf_tree2, operation);
 
+    dplot->SplitFaces(trimmed_faces);
+    dplot->WriteLog();
+
     for (int i = 0; i < surf_tree1.Count(); i++) {
        delete surf_tree1[i];
     }
@@ -3914,6 +3923,14 @@
 int
 ON_Boolean(ON_Brep *evaluated_brep, const ON_Brep *brep1, const ON_Brep 
*brep2, op_type operation)
 {
+    static int calls = 0;
+    ++calls;
+    std::ostringstream prefix;
+    prefix << "bool" << calls;
+    dplot = new DebugPlot(prefix.str().c_str());
+    dplot->Surfaces(brep1, brep2);
+    dplot->WriteLog();
+
     ON_ClassArray<ON_SimpleArray<TrimmedFace *> > trimmed_faces;
     try {
        /* Deal with the trivial cases up front */
@@ -3934,14 +3951,17 @@
            }
            evaluated_brep->ShrinkSurfaces();
            evaluated_brep->Compact();
+           dplot->WriteLog();
            return 0;
        }
        trimmed_faces = get_evaluated_faces(brep1, brep2, operation);
     } catch (InvalidBooleanOperation &e) {
        bu_log("%s", e.what());
+       dplot->WriteLog();
        return -1;
     } catch (GeometryGenerationError &e) {
        bu_log("%s", e.what());
+       dplot->WriteLog();
        return -1;
     }
 
@@ -3999,6 +4019,10 @@
        bu_log("%s", ON_String(ws).Array());
     }
 
+    dplot->WriteLog();
+    delete dplot;
+    dplot = NULL;
+
     return 0;
 }
 

Copied: brlcad/branches/bioh/src/libbrep/brep_defines.h (from rev 77302, 
brlcad/trunk/src/libbrep/brep_defines.h)
===================================================================
--- brlcad/branches/bioh/src/libbrep/brep_defines.h                             
(rev 0)
+++ brlcad/branches/bioh/src/libbrep/brep_defines.h     2020-10-01 13:15:27 UTC 
(rev 77303)
@@ -0,0 +1,71 @@
+/*                  B R E P _ D E F I N E S . H
+ * BRL-CAD
+ *
+ * Copyright (c) 2014 United States Government as represented by
+ * the U.S. Army Research Laboratory.
+ *
+ * This library is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU Lesser General Public License
+ * version 2.1 as published by the Free Software Foundation.
+ *
+ * This library is distributed in the hope that it will be useful, but
+ * WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
+ * Lesser General Public License for more details.
+ *
+ * You should have received a copy of the GNU Lesser General Public
+ * License along with this file; see the file named COPYING for more
+ * information.
+ */
+/** @file brep_defines.h
+ *
+ * Private defines.
+ *
+ */
+
+// The maximal depth for subdivision - trade-off between accuracy and
+// performance.
+#define NR_MAX_DEPTH 8
+#define MAX_PCI_DEPTH NR_MAX_DEPTH
+#define MAX_PSI_DEPTH NR_MAX_DEPTH
+#define MAX_CCI_DEPTH NR_MAX_DEPTH
+#define MAX_CSI_DEPTH NR_MAX_DEPTH
+#define MAX_SSI_DEPTH NR_MAX_DEPTH
+
+// Used to prevent an infinite loop in the unlikely event that we
+// can't provide a good starting point for the Newton-Raphson
+// Iteration.
+#define NR_MAX_ITERATIONS 100
+#define PCI_MAX_ITERATIONS NR_MAX_ITERATIONS
+#define PSI_MAX_ITERATIONS NR_MAX_ITERATIONS
+#define CCI_MAX_ITERATIONS NR_MAX_ITERATIONS
+#define CSI_MAX_ITERATIONS NR_MAX_ITERATIONS
+#define SSI_MAX_ITERATIONS NR_MAX_ITERATIONS
+
+// We make the default tolerance for PSI the same as that of curve and
+// surface intersections defined by openNURBS (see opennurbs_curve.h
+// and opennurbs_surface.h).
+#define NR_DEFAULT_TOLERANCE 0.001
+#define PCI_DEFAULT_TOLERANCE NR_DEFAULT_TOLERANCE
+#define PSI_DEFAULT_TOLERANCE NR_DEFAULT_TOLERANCE
+#define CCI_DEFAULT_TOLERANCE NR_DEFAULT_TOLERANCE
+#define CSI_DEFAULT_TOLERANCE NR_DEFAULT_TOLERANCE
+#define SSI_DEFAULT_TOLERANCE NR_DEFAULT_TOLERANCE
+
+// tol value used in ON_Intersect()s. We use a smaller tolerance than the
+// default one 0.001.
+#define INTERSECTION_TOL 1e-4
+
+// tol value used in ON_3dVector::IsParallelTo(). We use a smaller tolerance
+// than the default one ON_PI/180.
+#define ANGLE_TOL ON_PI/1800.0
+
+/*
+ * Local Variables:
+ * tab-width: 8
+ * mode: C
+ * indent-tabs-mode: t
+ * c-file-style: "stroustrup"
+ * End:
+ * ex: shiftwidth=4 tabstop=8
+ */

Copied: brlcad/branches/bioh/src/libbrep/debug_plot.cpp (from rev 77302, 
brlcad/trunk/src/libbrep/debug_plot.cpp)
===================================================================
--- brlcad/branches/bioh/src/libbrep/debug_plot.cpp                             
(rev 0)
+++ brlcad/branches/bioh/src/libbrep/debug_plot.cpp     2020-10-01 13:15:27 UTC 
(rev 77303)
@@ -0,0 +1,990 @@
+/*                  D E B U G _ P L O T . C P P
+ * BRL-CAD
+ *
+ * Copyright (c) 2014 United States Government as represented by
+ * the U.S. Army Research Laboratory.
+ *
+ * This library is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU Lesser General Public License
+ * version 2.1 as published by the Free Software Foundation.
+ *
+ * This library is distributed in the hope that it will be useful, but
+ * WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
+ * Lesser General Public License for more details.
+ *
+ * You should have received a copy of the GNU Lesser General Public
+ * License along with this file; see the file named COPYING for more
+ * information.
+ */
+/** @file debug_plot.cpp
+ *
+ * DebugPlot implementation. Currently borrows code from librt to
+ * handle the creation of vlists for brep geometry and conversion of
+ * those vlists to unix plot files.
+ */
+
+#include <iostream>
+#include <sstream>
+#include <string>
+#include "bu/log.h"
+#include "bn.h"
+#include "raytrace.h"
+#include "vmath.h"
+#include "debug_plot.h"
+#include "brep_except.h"
+
+static unsigned char surface1_color[] = {0, 0, 62};
+static unsigned char surface2_color[] = {62, 0, 0};
+static unsigned char surface1_highlight_color[] = {56, 56, 255};
+static unsigned char surface2_highlight_color[] = {255, 56, 56};
+
+static unsigned char tangent_color[] = {255, 255, 255};
+static unsigned char transverse_color[] = {255, 255, 0};
+static unsigned char overlap_color[] = {0, 255, 0};
+
+static unsigned char accepted_outerloop_color[] = {0, 255, 0};
+static unsigned char accepted_innerloop_color[] = {255, 0, 0};
+static unsigned char unknown_outerloop_color[] = {158, 158, 0};
+static unsigned char unknown_innerloop_color[] = {158, 158, 0};
+static unsigned char rejected_outerloop_color[] = {0, 62, 0};
+static unsigned char rejected_innerloop_color[] = {62, 0, 0};
+
+DebugPlot::DebugPlot(const char *basename) :
+    prefix(basename),
+    have_surfaces(false),
+    brep1_surf_count(0),
+    brep2_surf_count(0),
+    linked_curve_count(0)
+{
+    BU_LIST_INIT(&vlist_free_list);
+}
+
+DebugPlot::~DebugPlot()
+{
+    struct bn_vlist *vp;
+    while (BU_LIST_WHILE(vp, bn_vlist, &vlist_free_list)) {
+       BU_LIST_DEQUEUE(&(vp->l));
+       bu_free((char *)vp, "bn_vlist");
+    }
+}
+
+int
+DebugPlot::SurfacePairs(void)
+{
+    return (int)intersecting_surfaces.size();
+}
+
+int
+DebugPlot::IntersectingIsocurves(int ssx_idx)
+{
+    int max_isocsx_idx = (int)ssx_isocsx_events.size() - 1;
+    if (ssx_idx < 0 || ssx_idx > max_isocsx_idx) {
+       std::cerr << "DebugPlot::IntersectingIsocurves passed invalid ssx 
index.\n";
+       return 0;
+    }
+    return (int)ssx_isocsx_events[ssx_idx].size();
+}
+
+int
+DebugPlot::LinkedCurves(void)
+{
+    return linked_curve_count;
+}
+
+HIDDEN void
+rt_vlist_to_uplot(FILE *fp, const struct bu_list *vhead)
+{
+    struct bn_vlist *vp;
+
+    for (BU_LIST_FOR(vp, bn_vlist, vhead)) {
+        int i;
+        int nused = vp->nused;
+        const int *cmd = vp->cmd;
+        point_t *pt = vp->pt;
+
+       for (i = 0; i < nused; i++, cmd++, pt++) {
+           switch (*cmd) {
+               case BN_VLIST_POLY_START:
+               case BN_VLIST_TRI_START:
+                   break;
+               case BN_VLIST_POLY_MOVE:
+               case BN_VLIST_LINE_MOVE:
+               case BN_VLIST_TRI_MOVE:
+                   pdv_3move(fp, *pt);
+                   break;
+               case BN_VLIST_POLY_DRAW:
+               case BN_VLIST_POLY_END:
+               case BN_VLIST_LINE_DRAW:
+               case BN_VLIST_TRI_DRAW:
+               case BN_VLIST_TRI_END:
+                   pdv_3cont(fp, *pt);
+                   break;
+               default:
+                   bu_log("rt_vlist_to_uplot: unknown vlist cmd x%x\n",
+                          *cmd);
+           }
+       }
+    }
+}
+
+HIDDEN void
+write_plot_to_file(
+    const char *filename,
+    const struct bu_list *vhead,
+    const unsigned char *color)
+{
+    FILE *fp = fopen(filename, "w");
+
+    if (!color) {
+       unsigned char clr[] = {255, 0, 0};
+       color = clr;
+    }
+
+    pl_linmod(fp, "solid");
+    pl_color(fp, color[0], color[1], color[2]);
+    rt_vlist_to_uplot(fp, vhead);
+
+    fclose(fp);
+}
+
+void
+DebugPlot::WriteLog()
+{
+    std::ostringstream filename;
+
+    // First write out empty plots of different colors, we use this to
+    // "erase" unwanted overlays when running the dplot command.
+    struct bu_list vhead;
+    BU_LIST_INIT(&vhead);
+    point_t origin = {0.0, 0.0, 0.0};
+    BN_ADD_VLIST(&vlist_free_list, &vhead, origin, BN_VLIST_LINE_MOVE);
+
+    filename << prefix << "_empty0.plot3";
+    write_plot_to_file(filename.str().c_str(), &vhead, tangent_color);
+    filename.str("");
+    filename << prefix << "_empty1.plot3";
+    write_plot_to_file(filename.str().c_str(), &vhead, transverse_color);
+    filename.str("");
+    filename << prefix << "_empty2.plot3";
+    write_plot_to_file(filename.str().c_str(), &vhead, overlap_color);
+    filename.str("");
+    filename << prefix << "_empty3.plot3";
+    write_plot_to_file(filename.str().c_str(), &vhead, surface1_color);
+    filename.str("");
+    filename << prefix << "_empty4.plot3";
+    write_plot_to_file(filename.str().c_str(), &vhead, surface2_color);
+    filename.str("");
+    filename << prefix << "_empty5.plot3";
+    write_plot_to_file(filename.str().c_str(), &vhead, 
surface1_highlight_color);
+    filename.str("");
+    filename << prefix << "_empty6.plot3";
+    write_plot_to_file(filename.str().c_str(), &vhead, 
surface2_highlight_color);
+    filename.str("");
+    filename << prefix << "_empty7.plot3";
+    write_plot_to_file(filename.str().c_str(), &vhead, 
accepted_outerloop_color);
+    filename.str("");
+    filename << prefix << "_empty8.plot3";
+    write_plot_to_file(filename.str().c_str(), &vhead, 
accepted_innerloop_color);
+    filename.str("");
+    filename << prefix << "_empty9.plot3";
+    write_plot_to_file(filename.str().c_str(), &vhead, 
unknown_outerloop_color);
+    filename.str("");
+    filename << prefix << "_empty10.plot3";
+    write_plot_to_file(filename.str().c_str(), &vhead, 
unknown_innerloop_color);
+    filename.str("");
+    filename << prefix << "_empty11.plot3";
+    write_plot_to_file(filename.str().c_str(), &vhead, 
rejected_outerloop_color);
+    filename.str("");
+    filename << prefix << "_empty12.plot3";
+    write_plot_to_file(filename.str().c_str(), &vhead, 
rejected_innerloop_color);
+
+    // create dplot log file
+    filename.str("");
+    filename << prefix << ".dplot";
+    FILE *fp = fopen(filename.str().c_str(), "w");
+
+    // write out surface-surface intersections
+    fprintf(fp, "surfaces %d %d\n", brep1_surf_count, brep2_surf_count);
+    for (size_t i = 0; i < intersecting_surfaces.size(); ++i) {
+       std::pair<int, int> intersecting = intersecting_surfaces[i];
+
+       int events, b1_isocurves, intersecting_isocurves, b1_clipped, 
b2_clipped;
+
+       try {
+           events = ssx_events.at(i);
+       } catch (std::out_of_range &e) {
+           events = 0;
+       }
+       try {
+           std::pair<int, int> ccount = ssx_clipped_curves.at(i);
+           b1_clipped = ccount.first;
+           b2_clipped = ccount.second;
+       } catch (std::out_of_range &e) {
+           b1_clipped = b2_clipped = 0;
+       }
+       try {
+           b1_isocurves = ssx_isocsx_brep1_curves.at(i);
+       } catch (std::out_of_range &e) {
+           b1_isocurves = 0;
+       }
+       try {
+           intersecting_isocurves = (int)ssx_isocsx_events.at(i).size();
+       } catch (std::out_of_range &e) {
+           intersecting_isocurves = 0;
+       }
+
+       // b1si b2si finalevents b1ccurves b2ccurves b1_isocurve_xs 
total_isocurve_xs isocsx0_event0 ...
+       fprintf(fp, "ssx %d %d %d %d %d %d %d", intersecting.first,
+               intersecting.second, events, b1_clipped, b2_clipped,
+               b1_isocurves, intersecting_isocurves);
+
+       if (ssx_isocsx_events.size() > i) {
+           for (size_t j = 0; j < ssx_isocsx_events[i].size(); ++j) {
+               fprintf(fp, " %d", ssx_isocsx_events[i][j]);
+           }
+       }
+       fprintf(fp, "\n");
+    }
+
+    // write out linked curve count
+    if (linked_curve_count > 0) {
+       fprintf(fp, "linkedcurves %d\n", linked_curve_count);
+    }
+
+    // write out split faces
+    size_t split_faces = split_face_outerloop_curves.size();
+    if (split_faces > 0) {
+       fprintf(fp, "splitfaces %d\n", (int)split_faces);
+    }
+    for (size_t i = 0; i < split_faces; ++i) {
+       fprintf(fp, "splitface %d %d %d\n", (int)i,
+               split_face_outerloop_curves[i],
+               split_face_innerloop_curves[i]);
+    }
+    fclose(fp);
+    BN_FREE_VLIST(&vlist_free_list, &vhead);
+}
+
+HIDDEN double
+find_next_t(const ON_Curve* crv, double start_t, double step, double max_dist)
+{
+    ON_Interval dom = crv->Domain();
+    ON_3dPoint prev_pt = crv->PointAt(dom.ParameterAt(start_t));
+    ON_3dPoint next_pt;
+
+    // ensure that (start + step) < 1.0
+    if (start_t + step > 1.0) {
+       step = 1.0 - start_t - BN_TOL_DIST;
+    }
+    
+    // reduce step until next point is within tolerance
+    while (step > BN_TOL_DIST) {
+       next_pt = crv->PointAt(dom.ParameterAt(start_t + step));
+
+       if (prev_pt.DistanceTo(next_pt) <= max_dist) {
+           return start_t + step;
+       }
+       step /= 2.0;
+    }
+    // if we couldn't find a point within tolerance, give up and jump
+    // to end of domain
+    return 1.0;
+}
+
+void
+DebugPlot::Plot3DCurve(
+    const ON_Curve *crv,
+    const char *filename,
+    unsigned char *color,
+    struct bu_list *vlist /* = NULL */)
+{
+    struct bu_list vhead_tmp;
+    BU_LIST_INIT(&vhead_tmp);
+
+    struct bu_list *vhead = &vhead_tmp;
+    if (vlist) {
+       vhead = vlist;
+    }
+
+    ON_Interval crv_dom = crv->Domain();
+
+    // Insert first point.
+    point_t pt1;
+    ON_3dPoint p;
+    p = crv->PointAt(crv_dom.ParameterAt(0.0));
+    VMOVE(pt1, p);
+    BN_ADD_VLIST(&vlist_free_list, vhead, pt1, BN_VLIST_LINE_MOVE);
+
+    /* Dynamic sampling approach - start with an initial guess
+     * for the next point of one tenth of the domain length
+     * further down the domain from the previous value.  Set a
+     * maximum physical distance between points of 100 times
+     * the model tolerance.  Reduce the increment until the
+     * tolerance is satisfied, then add the point and use it
+     * as the starting point for the next calculation until
+     * the whole domain is finished.  Perhaps it would be more
+     * ideal to base the tolerance on some fraction of the
+     * curve bounding box dimensions?
+     */
+    double t = 0.0;
+    while (t < 1.0) {
+       t = find_next_t(crv, t, 0.1, BN_TOL_DIST * 100);
+       p = crv->PointAt(crv_dom.ParameterAt(t));
+       VMOVE(pt1, p);
+
+       BN_ADD_VLIST(&vlist_free_list, vhead, pt1, BN_VLIST_LINE_DRAW);
+    }
+
+    if (!vlist) {
+       write_plot_to_file(filename, vhead, color);
+       BN_FREE_VLIST(&vlist_free_list, vhead);
+    }
+}
+
+void
+DebugPlot::Plot3DCurveFrom2D(
+    const ON_Surface *surf,
+    const ON_Curve *crv,
+    const char *filename,
+    unsigned char *color,
+    bool decorate /* = false */)
+{
+    struct bu_list vhead;
+    BU_LIST_INIT(&vhead);
+
+    ON_Interval crv_dom = crv->Domain();
+
+    ON_3dPoint p, uv;
+
+    // Insert first point.
+    point_t pt1, first_pt, last_pt, prev_pt;
+    ON_3dVector normal;
+    uv = crv->PointAt(crv_dom.ParameterAt(0.0));
+    surf->EvNormal(uv.x, uv.y, p, normal);
+    VMOVE(first_pt, p);
+
+    uv = crv->PointAt(crv_dom.ParameterAt(1.0));
+    surf->EvNormal(uv.x, uv.y, p, normal);
+    VMOVE(last_pt, p);
+
+    bool closed = false;
+    if (VNEAR_EQUAL(first_pt, last_pt, BN_TOL_DIST)) {
+       closed = true;
+    }
+
+    VMOVE(pt1, first_pt);
+    BN_ADD_VLIST(&vlist_free_list, &vhead, pt1, BN_VLIST_LINE_MOVE);
+
+    /* Dynamic sampling approach - start with an initial guess
+     * for the next point of one tenth of the domain length
+     * further down the domain from the previous value.  Set a
+     * maximum physical distance between points of 100 times
+     * the model tolerance.  Reduce the increment until the
+     * tolerance is satisfied, then add the point and use it
+     * as the starting point for the next calculation until
+     * the whole domain is finished.  Perhaps it would be more
+     * ideal to base the tolerance on some fraction of the
+     * curve bounding box dimensions?
+     */
+    double t = 0.0;
+    bool first = true;
+    double min_mag = BN_TOL_DIST * 10.0;
+    double mag_tan = min_mag;
+    vect_t tangent = {0.0, 0.0, min_mag};
+    vect_t perp, barb;
+    while (t < 1.0) {
+       t = find_next_t(crv, t, 0.1, BN_TOL_DIST * 100);
+
+       uv = crv->PointAt(crv_dom.ParameterAt(t));
+       surf->EvNormal(uv.x, uv.y, p, normal);
+       VMOVE(prev_pt, pt1);
+       VMOVE(pt1, p);
+
+       if (first || !VNEAR_EQUAL(pt1, prev_pt, BN_TOL_DIST)) {
+           VSUB2(tangent, pt1, prev_pt);
+       }
+
+       if (decorate && first) {
+           first = false;
+
+           mag_tan = DIST_PNT_PNT(prev_pt, pt1);
+           mag_tan = FMAX(mag_tan, min_mag);
+
+           VUNITIZE(tangent);
+           VCROSS(perp, tangent, normal);
+
+           if (!closed) {
+               VSCALE(tangent, tangent, mag_tan);
+               VUNITIZE(perp);
+               VSCALE(perp, perp, mag_tan);
+
+               VADD3(barb, prev_pt, tangent, perp);
+               BN_ADD_VLIST(&vlist_free_list, &vhead, barb, 
BN_VLIST_LINE_DRAW);
+               BN_ADD_VLIST(&vlist_free_list, &vhead, prev_pt, 
BN_VLIST_LINE_MOVE);
+
+               VSCALE(perp, perp, -1.0);
+               VADD3(barb, prev_pt, tangent, perp);
+               BN_ADD_VLIST(&vlist_free_list, &vhead, barb, 
BN_VLIST_LINE_DRAW);
+               BN_ADD_VLIST(&vlist_free_list, &vhead, prev_pt, 
BN_VLIST_LINE_MOVE);
+           }
+       }
+       BN_ADD_VLIST(&vlist_free_list, &vhead, pt1, BN_VLIST_LINE_DRAW);
+    }
+    if (decorate) {
+       VUNITIZE(tangent);
+       VSCALE(tangent, tangent, -mag_tan);
+
+       VCROSS(perp, tangent, normal);
+       VUNITIZE(perp);
+       VSCALE(perp, perp, mag_tan);
+
+       VADD2(barb, pt1, perp);
+       if (!closed) {
+           VADD2(barb, barb, tangent);
+       }
+       BN_ADD_VLIST(&vlist_free_list, &vhead, barb, BN_VLIST_LINE_DRAW);
+       BN_ADD_VLIST(&vlist_free_list, &vhead, pt1, BN_VLIST_LINE_MOVE);
+
+       VSCALE(perp, perp, -1.0);
+       VADD2(barb, pt1, perp);
+       if (!closed) {
+           VADD2(barb, barb, tangent);
+       }
+       BN_ADD_VLIST(&vlist_free_list, &vhead, barb, BN_VLIST_LINE_DRAW);
+    }
+
+    write_plot_to_file(filename, &vhead, color);
+    BN_FREE_VLIST(&vlist_free_list, &vhead);
+}
+
+void
+DebugPlot::PlotBoundaryIsocurves(
+    struct bu_list *vlist,
+    const ON_Surface &surf,
+    int knot_dir)
+{
+    int surf_dir = 1 - knot_dir;
+    int knot_count = surf.SpanCount(surf_dir) + 1;
+
+    double *surf_knots = new double[knot_count];
+    surf.GetSpanVector(surf_dir, surf_knots);
+
+    // knots that can be boundaries of Bezier patches
+    ON_SimpleArray<double> surf_bknots;
+    surf_bknots.Append(surf_knots[0]);
+    for (int i = 1; i < knot_count; i++) {
+       if (surf_knots[i] > *(surf_bknots.Last())) {
+           surf_bknots.Append(surf_knots[i]);
+       }
+    }
+    delete[] surf_knots;
+
+    if (surf.IsClosed(surf_dir)) {
+       surf_bknots.Remove();
+    }
+
+    for (int i = 0; i < surf_bknots.Count(); i++) {
+       ON_Curve *surf_boundary_iso = surf.IsoCurve(knot_dir, surf_bknots[i]);
+       Plot3DCurve(surf_boundary_iso, NULL, NULL, vlist);
+       delete surf_boundary_iso;
+    }
+}
+
+void
+DebugPlot::PlotSurface(
+    const ON_Surface &surf,
+    const char *filename,
+    unsigned char *color)
+{
+    struct bu_list vhead;
+    BU_LIST_INIT(&vhead);
+
+    PlotBoundaryIsocurves(&vhead, surf, 0);
+    PlotBoundaryIsocurves(&vhead, surf, 1);
+
+    write_plot_to_file(filename, &vhead, color);
+
+    BN_FREE_VLIST(&vlist_free_list, &vhead);
+}
+
+
+void
+DebugPlot::Surfaces(const ON_Brep *brep1, const ON_Brep *brep2)
+{
+    if (!brep1 || !brep2) {
+       std::cerr << "error: dplot_surfaces: NULL args\n";
+       return;
+    }
+
+    brep1_surf_count = brep1->m_S.Count();
+    for (int i = 0; i < brep1->m_S.Count(); i++) {
+       ON_Surface *surf = brep1->m_S[i];
+       std::ostringstream filename;
+       filename << prefix << "_brep1_surface" << i << ".plot3";
+       PlotSurface(*surf, filename.str().c_str(), surface1_color);
+    }
+
+    brep2_surf_count = brep2->m_S.Count();
+    for (int i = 0; i < brep2->m_S.Count(); i++) {
+       ON_Surface *surf = brep2->m_S[i];
+       std::ostringstream filename;
+       filename << prefix << "_brep2_surface" << i << ".plot3";
+       PlotSurface(*surf, filename.str().c_str(), surface2_color);
+    }
+    have_surfaces = true;
+}
+
+int get_subcurve_inside_faces(const ON_Brep *brep1, const ON_Brep *brep2, int 
face_i1, int face_i2, ON_SSX_EVENT *event);
+
+void
+DebugPlot::SSX(
+    const ON_ClassArray<ON_SSX_EVENT> &events,
+    const ON_Brep *brep1, int brep1_surf,
+    const ON_Brep *brep2, int brep2_surf)
+{
+    ON_Surface *surf;
+    std::ostringstream filename;
+
+    // create highlighted plot of brep1 surface if it doesn't exist
+    filename << prefix << "_highlight_brep1_surface" << brep1_surf << ".plot3";
+    if (!bu_file_exists(filename.str().c_str(), NULL)) {
+       surf = brep1->m_S[brep1_surf];
+       PlotSurface(*surf, filename.str().c_str(), surface1_highlight_color);
+    }
+
+    // create highlighted plot of brep2 surface if it doesn't exist
+    filename.str("");
+    filename << prefix << "_highlight_brep2_surface" << brep2_surf << ".plot3";
+    if (!bu_file_exists(filename.str().c_str(), NULL)) {
+       surf = brep2->m_S[brep2_surf];
+       PlotSurface(*surf, filename.str().c_str(), surface2_highlight_color);
+    }
+
+    // create plot of the intersections between these surfaces
+    surf = brep1->m_S[brep1_surf];
+    size_t ssx_idx = intersecting_surfaces.size();
+    int plot_count = 0;
+    for (int i = 0; i < events.Count(); ++i) {
+       filename.str("");
+       filename << prefix << "_ssx" << ssx_idx << "_event" << plot_count <<
+           ".plot3";
+
+       if (events[i].m_type == ON_SSX_EVENT::ssx_tangent) {
+           Plot3DCurveFrom2D(surf, events[i].m_curveA,
+                   filename.str().c_str(), tangent_color, true);
+           ++plot_count;
+       } else if (events[i].m_type == ON_SSX_EVENT::ssx_transverse) {
+           Plot3DCurveFrom2D(surf, events[i].m_curveA,
+                   filename.str().c_str(), transverse_color, true);
+           ++plot_count;
+       } else if (events[i].m_type == ON_SSX_EVENT::ssx_overlap) {
+           Plot3DCurveFrom2D(surf, events[i].m_curveA,
+                   filename.str().c_str(), overlap_color, true);
+           ++plot_count;
+       }
+    }
+    // stash surface indices and event count
+    std::pair<int, int> ssx_pair(brep1_surf, brep2_surf);
+    intersecting_surfaces.push_back(ssx_pair);
+    ssx_events.push_back(plot_count);
+}
+
+void
+DebugPlot::IsoCSX(
+    const ON_SimpleArray<ON_X_EVENT> &events,
+    const ON_Curve *isocurve,
+    bool is_brep1_iso) // is the isocurve from brep1?
+{
+    size_t ssx_idx = intersecting_surfaces.size();
+
+    // create plot of the intersections between the curve and surface
+    while (ssx_isocsx_events.size() < (ssx_idx + 1)) {
+       ssx_isocsx_events.push_back(std::vector<int>());
+    }
+    size_t isocsx_idx = ssx_isocsx_events[ssx_idx].size();
+    int plot_count = 0;
+    for (int i = 0; i < events.Count(); ++i) {
+       if (events[i].m_type == ON_X_EVENT::csx_overlap) {
+           std::ostringstream filename;
+           filename << prefix << "_ssx" << ssx_idx << "_isocsx" << isocsx_idx
+               << "_event" << plot_count++ << ".plot3";
+
+           try {
+               ON_Curve *event_curve = sub_curve(isocurve, events[i].m_a[0],
+                       events[i].m_a[1]);
+               Plot3DCurve(event_curve, filename.str().c_str(), overlap_color);
+           } catch (InvalidInterval &e) {
+               std::cerr << "error: IsoCSX event contains degenerate 
interval\n";
+           }
+       }
+    }
+    if (plot_count) {
+       // create highlighted plot of isocurve if it doesn't already exist
+       std::ostringstream filename;
+       filename << prefix << "_highlight_ssx" << ssx_idx << "_isocurve" <<
+           isocsx_idx << ".plot3";
+       if (!bu_file_exists(filename.str().c_str(), NULL)) {
+           if (is_brep1_iso) {
+               Plot3DCurve(isocurve, filename.str().c_str(),
+                       surface1_highlight_color);
+           } else {
+               Plot3DCurve(isocurve, filename.str().c_str(),
+                       surface2_highlight_color);
+           }
+       }
+
+       // remember event count for this isocsx
+       ssx_isocsx_events[ssx_idx].push_back(plot_count);
+
+       // remember how many events are for brep1 isocurve and brep2 surface,
+       if (is_brep1_iso) {
+           while (ssx_isocsx_brep1_curves.size() < (ssx_idx + 1)) {
+               ssx_isocsx_brep1_curves.push_back(0);
+           }
+           ++ssx_isocsx_brep1_curves[ssx_idx];
+       }
+    }
+}
+
+void
+DebugPlot::ClippedFaceCurves(
+    const ON_Surface *surf1,
+    const ON_Surface *surf2,
+    const ON_SimpleArray<ON_Curve *> &face1_curves,
+    const ON_SimpleArray<ON_Curve *> &face2_curves)
+{
+    // plot clipped tangent/transverse/overlap curves
+    size_t ssx_idx = intersecting_surfaces.size() - 1;
+    for (int i = 0; i < face1_curves.Count(); ++i) {
+       std::ostringstream filename;
+       filename << prefix << "_ssx" << ssx_idx << "_brep1face_clipped_curve" 
<< i << ".plot3";
+       Plot3DCurveFrom2D(surf1, face1_curves[i], filename.str().c_str(),
+               surface1_highlight_color, true);
+    }
+    for (int i = 0; i < face2_curves.Count(); ++i) {
+       std::ostringstream filename;
+       filename << prefix << "_ssx" << ssx_idx << "_brep2face_clipped_curve" 
<< i << ".plot3";
+       Plot3DCurveFrom2D(surf2, face2_curves[i], filename.str().c_str(),
+               surface2_highlight_color, true);
+    }
+
+    while (ssx_clipped_curves.size() < (ssx_idx + 1)) {
+       ssx_clipped_curves.push_back(std::pair<int, int>(0, 0));
+    }
+    std::pair<int, int> counts(face1_curves.Count(), face2_curves.Count());
+    ssx_clipped_curves[ssx_idx] = counts;
+}
+
+struct TrimmedFace {
+    // curve segments in the face's outer loop
+    ON_SimpleArray<ON_Curve *> m_outerloop;
+    // several inner loops, each has some curves
+    std::vector<ON_SimpleArray<ON_Curve *> > m_innerloop;
+    const ON_BrepFace *m_face;
+    enum {
+       UNKNOWN = -1,
+       NOT_BELONG = 0,
+       BELONG = 1
+    } m_belong_to_final;
+    bool m_rev;
+
+    // Default constructor
+    TrimmedFace()
+    {
+       m_face = NULL;
+       m_belong_to_final = UNKNOWN;
+       m_rev = false;
+    }
+
+    // Destructor
+    ~TrimmedFace()
+    {
+       // Delete the curve segments if it's not belong to the result.
+       if (m_belong_to_final != BELONG) {
+           for (int i = 0; i < m_outerloop.Count(); i++) {
+               if (m_outerloop[i]) {
+                   delete m_outerloop[i];
+                   m_outerloop[i] = NULL;
+               }
+           }
+           for (unsigned int i = 0; i < m_innerloop.size(); i++) {
+               for (int j = 0; j < m_innerloop[i].Count(); j++) {
+                   if (m_innerloop[i][j]) {
+                       delete m_innerloop[i][j];
+                       m_innerloop[i][j] = NULL;
+                   }
+               }
+           }
+       }
+    }
+
+    TrimmedFace *Duplicate() const
+    {
+       TrimmedFace *out = new TrimmedFace();
+       out->m_face = m_face;
+       for (int i = 0; i < m_outerloop.Count(); i++) {
+           if (m_outerloop[i]) {
+               out->m_outerloop.Append(m_outerloop[i]->Duplicate());
+           }
+       }
+       out->m_innerloop = m_innerloop;
+       for (unsigned int i = 0; i < m_innerloop.size(); i++) {
+           for (int j = 0; j < m_innerloop[i].Count(); j++) {
+               if (m_innerloop[i][j]) {
+                   out->m_innerloop[i][j] = m_innerloop[i][j]->Duplicate();
+               }
+           }
+       }
+       return out;
+    }
+};
+
+void
+DebugPlot::SplitFaces(
+    const ON_ClassArray<ON_SimpleArray<TrimmedFace *> > &split_faces)
+{
+    for (int i = 0; i < split_faces.Count(); ++i) {
+       for (int j = 0; j < split_faces[i].Count(); ++j) {
+           TrimmedFace *face = split_faces[i][j];
+
+           unsigned char *outerloop_color = unknown_outerloop_color;
+           unsigned char *innerloop_color = unknown_innerloop_color;
+           switch (face->m_belong_to_final) {
+               case TrimmedFace::NOT_BELONG:
+                   outerloop_color = rejected_outerloop_color;
+                   innerloop_color = rejected_innerloop_color;
+                   break;
+               case TrimmedFace::BELONG:
+                   outerloop_color = accepted_outerloop_color;
+                   innerloop_color = accepted_innerloop_color;
+                   break;
+               default:
+                   outerloop_color = unknown_outerloop_color;
+                   innerloop_color = unknown_innerloop_color;
+           }
+
+           int split_face_count = split_face_outerloop_curves.size();
+           for (int k = 0; k < face->m_outerloop.Count(); ++k) {
+               std::ostringstream filename;
+               filename << prefix << "_split_face" << split_face_count <<
+                   "_outerloop_curve" << k << ".plot3";
+
+               Plot3DCurveFrom2D(face->m_face->SurfaceOf(),
+                       face->m_outerloop[k], filename.str().c_str(),
+                       outerloop_color);
+           }
+           split_face_outerloop_curves.push_back(face->m_outerloop.Count());
+
+           int innerloop_count = 0;
+           for (size_t k = 0; k < face->m_innerloop.size(); ++k) {
+               for (int l = 0; l < face->m_innerloop[k].Count(); ++l) {
+                   std::ostringstream filename;
+                   filename << prefix << "_split_face" << split_face_count <<
+                       "_innerloop_curve" << innerloop_count++ << ".plot3";
+
+                   Plot3DCurveFrom2D(face->m_face->SurfaceOf(),
+                           face->m_innerloop[k][l], filename.str().c_str(),
+                           innerloop_color);
+               }
+           }
+           split_face_innerloop_curves.push_back(innerloop_count);
+       }
+    }
+}
+
+void append_to_polycurve(ON_Curve *curve, ON_PolyCurve &polycurve);
+
+struct SSICurve {
+    ON_Curve *m_curve;
+
+    SSICurve()
+    {
+       m_curve = NULL;
+    }
+
+    SSICurve(ON_Curve *curve)
+    {
+       m_curve = curve;
+    }
+
+    SSICurve *Duplicate() const
+    {
+       SSICurve *out = new SSICurve();
+       if (out != NULL) {
+           *out = *this;
+           out->m_curve = m_curve->Duplicate();
+       }
+       return out;
+    }
+};
+
+struct LinkedCurve {
+private:
+    ON_Curve *m_curve; // an explicit storage of the whole curve
+public:
+    // The curves contained in this LinkedCurve, including
+    // the information needed by the connectivity graph
+    ON_SimpleArray<SSICurve> m_ssi_curves;
+
+    // Default constructor
+    LinkedCurve()
+    {
+       m_curve = NULL;
+    }
+
+    ~LinkedCurve()
+    {
+       if (m_curve) {
+           delete m_curve;
+       }
+       m_curve = NULL;
+    }
+
+    LinkedCurve &operator= (const LinkedCurve &_lc)
+    {
+       m_curve = _lc.m_curve ? _lc.m_curve->Duplicate() : NULL;
+       m_ssi_curves = _lc.m_ssi_curves;
+       return *this;
+    }
+
+    ON_3dPoint PointAtStart() const
+    {
+       if (m_ssi_curves.Count()) {
+           return m_ssi_curves[0].m_curve->PointAtStart();
+       } else {
+           return ON_3dPoint::UnsetPoint;
+       }
+    }
+
+    ON_3dPoint PointAtEnd() const
+    {
+       if (m_ssi_curves.Count()) {
+           return m_ssi_curves.Last()->m_curve->PointAtEnd();
+       } else {
+           return ON_3dPoint::UnsetPoint;
+       }
+    }
+
+    bool IsClosed() const
+    {
+       if (m_ssi_curves.Count() == 0) {
+           return false;
+       }
+       return PointAtStart().DistanceTo(PointAtEnd()) < ON_ZERO_TOLERANCE;
+    }
+
+    bool IsValid() const
+    {
+       // Check whether the curve has "gaps".
+       for (int i = 1; i < m_ssi_curves.Count(); i++) {
+           if 
(m_ssi_curves[i].m_curve->PointAtStart().DistanceTo(m_ssi_curves[i - 
1].m_curve->PointAtEnd()) >= ON_ZERO_TOLERANCE) {
+               bu_log("The LinkedCurve is not valid.\n");
+               return false;
+           }
+       }
+       return true;
+    }
+
+    bool Reverse()
+    {
+       ON_SimpleArray<SSICurve> new_array;
+       for (int i = m_ssi_curves.Count() - 1; i >= 0; i--) {
+           if (!m_ssi_curves[i].m_curve->Reverse()) {
+               return false;
+           }
+           new_array.Append(m_ssi_curves[i]);
+       }
+       m_ssi_curves = new_array;
+       return true;
+    }
+
+    void Append(const LinkedCurve &lc)
+    {
+       m_ssi_curves.Append(lc.m_ssi_curves.Count(), lc.m_ssi_curves.Array());
+    }
+
+    void Append(const SSICurve &sc)
+    {
+       m_ssi_curves.Append(sc);
+    }
+
+    void AppendCurvesToArray(ON_SimpleArray<ON_Curve *> &arr) const
+    {
+       for (int i = 0; i < m_ssi_curves.Count(); i++) {
+           arr.Append(m_ssi_curves[i].m_curve->Duplicate());
+       }
+    }
+
+    const ON_Curve *Curve()
+    {
+       if (m_curve != NULL) {
+           return m_curve;
+       }
+       if (m_ssi_curves.Count() == 0 || !IsValid()) {
+           return NULL;
+       }
+       ON_PolyCurve *polycurve = new ON_PolyCurve;
+       for (int i = 0; i < m_ssi_curves.Count(); i++) {
+           append_to_polycurve(m_ssi_curves[i].m_curve->Duplicate(), 
*polycurve);
+       }
+       m_curve = polycurve;
+       return m_curve;
+    }
+
+    const ON_3dPoint PointAt(double t)
+    {
+       const ON_Curve *c = Curve();
+       if (c == NULL) {
+           return ON_3dPoint::UnsetPoint;
+       }
+       return c->PointAt(t);
+    }
+
+    const ON_Interval Domain()
+    {
+       const ON_Curve *c = Curve();
+       if (c == NULL) {
+           return ON_Interval::EmptyInterval;
+       }
+       return c->Domain();
+    }
+
+    ON_Curve *SubCurve(double t1, double t2)
+    {
+       const ON_Curve *c = Curve();
+       if (c == NULL) {
+           return NULL;
+       }
+       try {
+           return sub_curve(c, t1, t2);
+       } catch (InvalidInterval &e) {
+           bu_log("%s", e.what());
+           return NULL;
+       }
+    }
+};
+
+void
+DebugPlot::LinkedCurves(
+    const ON_Surface *surf,
+    ON_ClassArray<LinkedCurve> &linked_curves)
+{
+    for (int i = 0; i < linked_curves.Count(); ++i) {
+       const ON_Curve *linked_curve = linked_curves[i].Curve();
+
+       std::ostringstream filename;
+       filename << prefix << "_linked_curve" << linked_curve_count++ << 
".plot3";
+
+       Plot3DCurveFrom2D(surf, linked_curve, filename.str().c_str(), 
transverse_color);
+    }
+}
+
+// Local Variables:
+// tab-width: 8
+// mode: C++
+// c-basic-offset: 4
+// indent-tabs-mode: t
+// c-file-style: "stroustrup"
+// End:
+// ex: shiftwidth=4 tabstop=8

Copied: brlcad/branches/bioh/src/libbrep/debug_plot.h (from rev 77302, 
brlcad/trunk/src/libbrep/debug_plot.h)
===================================================================
--- brlcad/branches/bioh/src/libbrep/debug_plot.h                               
(rev 0)
+++ brlcad/branches/bioh/src/libbrep/debug_plot.h       2020-10-01 13:15:27 UTC 
(rev 77303)
@@ -0,0 +1,141 @@
+/*                    D E B U G _ P L O T . H
+ * BRL-CAD
+ *
+ * Copyright (c) 2014 United States Government as represented by
+ * the U.S. Army Research Laboratory.
+ *
+ * This library is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU Lesser General Public License
+ * version 2.1 as published by the Free Software Foundation.
+ *
+ * This library is distributed in the hope that it will be useful, but
+ * WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
+ * Lesser General Public License for more details.
+ *
+ * You should have received a copy of the GNU Lesser General Public
+ * License along with this file; see the file named COPYING for more
+ * information.
+ */
+/** @file debug_plot.h
+ *
+ * Class used to write out unix plot files representing brep geometry
+ * and intersection events from various stages of brep boolean
+ * evaluation.
+ *
+ * Also outputs a parsable log file with implicit information about
+ * the output plot files.
+ */
+
+#ifndef DEBUG_PLOT_H
+#define DEBUG_PLOT_H
+#include "bu/list.h"
+#include "raytrace.h"
+
+struct TrimmedFace;
+struct LinkedCurve;
+
+class DebugPlot {
+public:
+    // prefix all dplot output files with 'basename'
+    DebugPlot(const char *basename);
+
+    ~DebugPlot();
+
+    // write plot files for all surfaces of two breps
+    void Surfaces(const ON_Brep *brep1, const ON_Brep *brep2);
+
+    // record a surface surface intersection
+    void SSX(
+       const ON_ClassArray<ON_SSX_EVENT> &events,
+       const ON_Brep *brep1, int brep1_surf,
+       const ON_Brep *brep2, int brep2_surf);
+
+    // record surface surface isocurve intersections
+    void IsoCSX(
+       const ON_SimpleArray<ON_X_EVENT> &events,
+       const ON_Curve *isocurve,
+       bool is_brep1_iso);
+
+    // record clipped surface-surface intersection curves
+    void ClippedFaceCurves(
+       const ON_Surface *surf1,
+       const ON_Surface *surf2,
+       const ON_SimpleArray<ON_Curve *> &face1_curves,
+       const ON_SimpleArray<ON_Curve *> &face2_curves);
+
+    // write out the log file that the dplot command references to
+    // navigate the generated plot files
+    void WriteLog();
+
+    // get the number of intersecting surface pairs recorded
+    int SurfacePairs();
+
+    // get the number of isocurves that intersect either surface in
+    // given surface pair
+    int IntersectingIsocurves(int ssx_idx);
+
+    // get the number of linked curves recorded
+    int LinkedCurves();
+
+    void SplitFaces(
+       const ON_ClassArray<ON_SimpleArray<TrimmedFace *> > &split_faces);
+
+    void LinkedCurves(
+       const ON_Surface *surf,
+       ON_ClassArray<LinkedCurve> &linked_curves);
+
+    void
+    Plot3DCurveFrom2D(
+       const ON_Surface *surf,
+       const ON_Curve *crv,
+       const char *filename,
+       unsigned char *color,
+       bool decorate = false
+       );
+
+    void
+    Plot3DCurve(
+       const ON_Curve *crv,
+       const char *filename,
+       unsigned char *color,
+       struct bu_list *vlist = NULL);
+
+private:
+    struct bu_list vlist_free_list;
+    std::string prefix;
+    bool have_surfaces;
+    int brep1_surf_count;
+    int brep2_surf_count;
+    int linked_curve_count;
+    std::vector< std::pair<int, int> > intersecting_surfaces; // ssx surface 
index pairs
+    std::vector<int> ssx_events; // num final events of each ssx
+    std::vector< std::vector<int> > ssx_isocsx_events; // num events for each 
isocsx of each ssx
+    std::vector<int> ssx_isocsx_brep1_curves; // num ssx isocsx events using 
brep1 isocurves
+    std::vector< std::pair<int, int> > ssx_clipped_curves; // num clipped 
intersection curves
+    std::vector<int> split_face_outerloop_curves;
+    std::vector<int> split_face_innerloop_curves;
+
+    void PlotSurface(
+       const ON_Surface &surf,
+       const char *filename,
+       unsigned char *color);
+
+    void
+    PlotBoundaryIsocurves(
+       struct bu_list *vlist,
+       const ON_Surface &surf,
+       int knot_dir);
+};
+
+#endif
+
+/*
+ * Local Variables:
+ * tab-width: 8
+ * mode: C
+ * indent-tabs-mode: t
+ * c-file-style: "stroustrup"
+ * End:
+ * ex: shiftwidth=4 tabstop=8
+ */

Modified: brlcad/branches/bioh/src/libbrep/intersect.cpp
===================================================================
--- brlcad/branches/bioh/src/libbrep/intersect.cpp      2020-10-01 13:13:00 UTC 
(rev 77302)
+++ brlcad/branches/bioh/src/libbrep/intersect.cpp      2020-10-01 13:15:27 UTC 
(rev 77303)
@@ -21,6 +21,8 @@
  *
  * Implementation of intersection routines openNURBS left out.
  *
+ * Additional documentation can be found in the "NURBS Boolean Evaluation
+ * Development Guide" docbook article (bool_eval_development.html).
  */
 
 #include "common.h"
@@ -38,42 +40,15 @@
 #include "brep/defines.h"
 #include "brep/intersect.h"
 #include "brep/util.h"
+#include "debug_plot.h"
 #include "brep_except.h"
+#include "brep_defines.h"
 
+extern DebugPlot *dplot;
 
 // Whether to output the debug messages about b-rep intersections.
 static int DEBUG_BREP_INTERSECT = 0;
 
-// The maximal depth for subdivision - trade-off between accuracy and
-// performance.
-#define NR_MAX_DEPTH 8
-#define MAX_PCI_DEPTH NR_MAX_DEPTH
-#define MAX_PSI_DEPTH NR_MAX_DEPTH
-#define MAX_CCI_DEPTH NR_MAX_DEPTH
-#define MAX_CSI_DEPTH NR_MAX_DEPTH
-#define MAX_SSI_DEPTH NR_MAX_DEPTH
-
-
-// We make the default tolerance for PSI the same as that of curve and
-// surface intersections defined by openNURBS (see opennurbs_curve.h
-// and opennurbs_surface.h).
-#define NR_DEFAULT_TOLERANCE 0.001
-#define PCI_DEFAULT_TOLERANCE NR_DEFAULT_TOLERANCE
-#define PSI_DEFAULT_TOLERANCE NR_DEFAULT_TOLERANCE
-#define CCI_DEFAULT_TOLERANCE NR_DEFAULT_TOLERANCE
-#define CSI_DEFAULT_TOLERANCE NR_DEFAULT_TOLERANCE
-#define SSI_DEFAULT_TOLERANCE NR_DEFAULT_TOLERANCE
-
-// Used to prevent an infinite loop in the unlikely event that we
-// can't provide a good starting point for the Newton-Raphson
-// Iteration.
-#define NR_MAX_ITERATIONS 100
-#define PCI_MAX_ITERATIONS NR_MAX_ITERATIONS
-#define PSI_MAX_ITERATIONS NR_MAX_ITERATIONS
-#define CCI_MAX_ITERATIONS NR_MAX_ITERATIONS
-#define CSI_MAX_ITERATIONS NR_MAX_ITERATIONS
-#define SSI_MAX_ITERATIONS NR_MAX_ITERATIONS
-
 class XEventProxy {
 public:
     XEventProxy(ON_X_EVENT::TYPE type);
@@ -2556,10 +2531,29 @@
     return (pointA.DistanceTo(pointB) < isect_tol) && !std::isnan(uA) && 
!std::isnan(vA) && !std::isnan(uB) & !std::isnan(vB);
 }
 
+// if curve end is greater than tol distance from pt, append a linear
+// segment to the curve so it extends to the pt
+HIDDEN void
+extend_curve_end_to_pt(ON_Curve *&curve, ON_3dPoint pt, double tol)
+{
+    ON_NurbsCurve *nc = curve->NurbsCurve();
+    if (nc->PointAtEnd().DistanceTo(pt) > tol) {
+       ON_LineCurve line_bridge(nc->PointAtEnd(), pt);
 
+       ON_NurbsCurve bridge;
+       if (line_bridge.GetNurbForm(bridge)) {
+           nc->Append(bridge);
+       }
+       delete curve;
+       curve = nc;
+    }
+}
+
 HIDDEN ON_Curve *
 link_curves(ON_Curve *&c1, ON_Curve *&c2)
 {
+    extend_curve_end_to_pt(c1, c2->PointAtStart(), ON_ZERO_TOLERANCE);
+
     ON_NurbsCurve *nc1 = c1->NurbsCurve();
     ON_NurbsCurve *nc2 = c2->NurbsCurve();
     if (nc1 && nc2) {
@@ -2578,6 +2572,16 @@
     return NULL;
 }
 
+// if curve start and end are within tolerance, append a linear
+// segment to the curve to close it completely so it passes
+// IsClosed() tests
+HIDDEN void
+fill_gap_if_closed(ON_Curve *&curve, double tol)
+{
+    if (curve->PointAtStart().DistanceTo(curve->PointAtEnd()) <= tol) {
+       extend_curve_end_to_pt(curve, curve->PointAtStart(), ON_ZERO_TOLERANCE);
+    }
+}
 
 struct OverlapSegment {
     ON_Curve *m_curve3d, *m_curveA, *m_curveB;
@@ -2969,17 +2973,10 @@
     bool ret = false;
 
     if (iso.overlap_t[0] < iso.overlap_t[1]) {
-       bool at_first_knot = iso.src.knot.IsFirst();
-       bool at_last_knot = iso.src.knot.IsLast();
-       bool closed_at_iso = surf1->IsClosed(1 - iso.src.knot.dir) != 0;
+       int location = isocurve_surface_overlap_location(iso, surf1, surf2,
+               surf2_tree, isect_tol, isect_tol1);
 
-       ret = true;
-       if (closed_at_iso || (!at_first_knot && !at_last_knot)) {
-           int location = isocurve_surface_overlap_location(iso, surf1,
-                                                            surf2, surf2_tree, 
isect_tol, isect_tol1);
-
-           ret = (location == ON_OVERLAP_BOUNDARY);
-       }
+       ret = (location == ON_OVERLAP_BOUNDARY);
     }
     return ret;
 }
@@ -3513,6 +3510,7 @@
 HIDDEN void
 find_overlap_boundary_curves(
     ON_SimpleArray<OverlapSegment *> &overlaps,
+    ON_ClassArray<ON_SSX_EVENT> &csx_events,
     ON_3dPointArray &isocurve_3d,
     ON_2dPointArray &isocurveA_2d,
     ON_2dPointArray &isocurveB_2d,
@@ -3554,6 +3552,9 @@
            ON_Intersect(surf1_isocurve, surf2, events, isect_tol,
                         overlap_tol, 0, 0, 0, &overlap2d);
 
+           dplot->IsoCSX(events, surf1_isocurve, is_surfA_iso);
+           dplot->WriteLog();
+
            append_csx_event_points(isocurve_3d, isocurve2_2d, events);
 
            for (int k = 0; k < events.Count(); k++) {
@@ -3575,6 +3576,36 @@
                    if (curve_on_overlap_boundary) {
                        append_overlap_segments(overlaps, iso, overlap2d[k],
                                                surf1);
+                   } else {
+                       // the intersection isn't part of a
+                       // surface-surface overlap, but we want it all
+                       // the same
+                       ON_SimpleArray<OverlapSegment *> tmp_overlaps;
+
+                       append_overlap_segments(tmp_overlaps, iso, 
overlap2d[k], surf1);
+
+                       for (int l = 0; l < tmp_overlaps.Count(); ++l) {
+                           ON_SSX_EVENT ssx_event;
+
+                           int ret = set_ssx_event_from_curves(ssx_event,
+                                   tmp_overlaps[l]->m_curve3d,
+                                   tmp_overlaps[l]->m_curveA,
+                                   tmp_overlaps[l]->m_curveB, surfA, surfB);
+                           if (ret != 0) {
+                               bu_log("warning: reverse failed.");
+                           }
+                           csx_events.Append(ssx_event);
+
+                           // set the curves to NULL so they aren't
+                           // deleted by destructors
+                           tmp_overlaps[l]->m_curve3d = NULL;
+                           tmp_overlaps[l]->m_curveA = NULL;
+                           tmp_overlaps[l]->m_curveB = NULL;
+
+                           ssx_event.m_curve3d = NULL;
+                           ssx_event.m_curveA = NULL;
+                           ssx_event.m_curveB = NULL;
+                       }
                    }
                }
            }
@@ -3735,12 +3766,25 @@
     ON_2dPointArray curve_uvA, curve_uvB, tmp_curve_uvA, tmp_curve_uvB;
 
     ON_SimpleArray<OverlapSegment *> overlaps;
-    find_overlap_boundary_curves(overlaps, tmp_curvept, tmp_curve_uvA,
+    ON_ClassArray<ON_SSX_EVENT> csx_events;
+
+    find_overlap_boundary_curves(overlaps, csx_events, tmp_curvept, 
tmp_curve_uvA,
                                 tmp_curve_uvB, surfA, surfB, treeA, treeB, 
isect_tol, isect_tolA,
                                 isect_tolB, overlap_tol);
+
     split_overlaps_at_intersections(overlaps, surfA, surfB, treeA, treeB,
                                    isect_tol, isect_tolA, isect_tolB);
 
+    // add csx_events
+    for (int i = 0; i < csx_events.Count(); ++i) {
+       x.Append(csx_events[i]);
+
+       // set the curves to NULL so they aren't deleted by destructor
+       csx_events[i].m_curve3d = NULL;
+       csx_events[i].m_curveA = NULL;
+       csx_events[i].m_curveB = NULL;
+    }
+
     // find the neighbors for every overlap segment
     ON_SimpleArray<bool> start_linked(overlaps.Count()), 
end_linked(overlaps.Count());
     for (int i = 0; i < overlaps.Count(); i++) {
@@ -3875,6 +3919,9 @@
                delete overlaps[j];
                overlaps[j] = NULL;
            }
+           fill_gap_if_closed(overlaps[i]->m_curve3d, isect_tol);
+           fill_gap_if_closed(overlaps[i]->m_curveA, isect_tolA);
+           fill_gap_if_closed(overlaps[i]->m_curveB, isect_tolB);
        }
     }
 

Modified: brlcad/branches/bioh/src/libbrep/tests/CMakeLists.txt
===================================================================
--- brlcad/branches/bioh/src/libbrep/tests/CMakeLists.txt       2020-10-01 
13:13:00 UTC (rev 77302)
+++ brlcad/branches/bioh/src/libbrep/tests/CMakeLists.txt       2020-10-01 
13:15:27 UTC (rev 77303)
@@ -14,15 +14,9 @@
   vsp.stp
   )
 
-BRLCAD_ADDEXEC(brep_cdt_mesh brep_cdt_mesh.cpp "libbrep;libbg;libbn;libbu" 
TEST)
+BRLCAD_ADDEXEC(test_brep_ppx ppx.cpp "libbrep"  NO_INSTALL)
+add_test(NAME brep_ppx COMMAND test_brep_ppx)
 
-BRLCAD_ADDEXEC(test_point_intersect test_point_intersect.cpp "libbrep" 
NO_STRICT NO_INSTALL)
-
-BRLCAD_ADDEXEC(test_curve_intersect test_curve_intersect.cpp "libbrep" 
NO_STRICT NO_INSTALL)
-
-CMAKEFILES(${distcheck_files})
-CMAKEFILES(CMakeLists.txt)
-
 # Local Variables:
 # tab-width: 8
 # mode: cmake

Copied: brlcad/branches/bioh/src/libbrep/tests/ppx.cpp (from rev 77302, 
brlcad/trunk/src/libbrep/tests/ppx.cpp)
===================================================================
--- brlcad/branches/bioh/src/libbrep/tests/ppx.cpp                              
(rev 0)
+++ brlcad/branches/bioh/src/libbrep/tests/ppx.cpp      2020-10-01 13:15:27 UTC 
(rev 77303)
@@ -0,0 +1,235 @@
+/*                         P P X . C P P
+ * BRL-CAD
+ *
+ * Copyright (c) 2014 United States Government as represented by
+ * the U.S. Army Research Laboratory.
+ *
+ * This library is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU Lesser General Public License
+ * version 2.1 as published by the Free Software Foundation.
+ *
+ * This library is distributed in the hope that it will be useful, but
+ * WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
+ * Lesser General Public License for more details.
+ *
+ * You should have received a copy of the GNU Lesser General Public
+ * License along with this file; see the file named COPYING for more
+ * information.
+ */
+/** @file ppx.cpp
+ *
+ * Point-point intersection tests.
+ *
+ */
+
+#define NOMINMAX
+
+#include "common.h"
+#include "bu.h"
+#include "brep.h"
+#include <limits>
+#include <sstream>
+#include <string>
+#include "../brep_defines.h"
+
+// Here we determine an upper limit on the magnitude of coordinate
+// values for test points.
+//
+// We need to be able to calculate point to point distance as:
+//     sqrt((x2 - x1)^2 + (y2 - y1)^2 + (z2 - z1)^2)
+//
+// To prevent overflow, we must restrict the coordinate values such
+// that:
+//     (x2 - x1)^2 + (y2 - y1)^2 + (z2 - z1)^2 <= DBL_MAX
+//
+// If we want to choose an upper limit M on the magnitude of a
+// coordinate value to enforce this constraint, the restriction
+// simplifies to:
+//     coord1, coord2 in [-M, M] s.t.
+//     (coord2 - coord1)^2 <= DBL_MAX / 3.0
+//  => (coord2 - coord1) <= sqrt(DBL_MAX / 3.0)
+//
+// Knowing that the maximum value of (coord2 - coord1) is 2M, we can
+// solve for M:
+//     2M <= sqrt(DBL_MAX / 3.0)
+//  => M <= sqrt(DBL_MAX / 3.0) / 2.0
+//
+// We choose to use a value slightly less than the true DBL_MAX for
+// the calculation to avoid the possibility that floating point error
+// causes [3.0 * sqrt(DBL_MAX / 3.0)^2 <= DBL_MAX] to be false.
+static const double NEAR_DBL_MAX =
+    std::numeric_limits<double>::max() -
+    std::numeric_limits<double>::round_error();
+
+static const double COORD_MAG_MAX = sqrt(NEAR_DBL_MAX / 3.0) / 2.0;
+
+class PPX_Input {
+public:
+    PPX_Input()
+       : tol(0.0)
+    {
+    }
+    ON_3dPoint ptA;
+    ON_3dPoint ptB;
+    ON_ClassArray<ON_PX_EVENT> events;
+    bool default_tol;
+    double tol;
+};
+
+class PPX_Output {
+public:
+    bool status;
+    ON_ClassArray<ON_PX_EVENT> events;
+
+    bool Equals(std::string &log, const PPX_Output &other);
+};
+
+static const double EVENT_EQUAL_TOL =
+    std::numeric_limits<double>::round_error();
+
+static bool
+point_events_equal(ON_PX_EVENT a, ON_PX_EVENT b)
+{
+    if (a.m_type != b.m_type) {
+       return false;
+    }
+    if (a.m_A.DistanceTo(b.m_A) >= EVENT_EQUAL_TOL) {
+       return false;
+    }
+    if (a.m_B.DistanceTo(b.m_B) >= EVENT_EQUAL_TOL) {
+       return false;
+    }
+    if (a.m_b.DistanceTo(b.m_b) >= EVENT_EQUAL_TOL) {
+       return false;
+    }
+    if (a.m_Mid.DistanceTo(b.m_Mid) >= EVENT_EQUAL_TOL) {
+       return false;
+    }
+    if (!ON_NearZero(a.m_radius - b.m_radius, EVENT_EQUAL_TOL)) {
+       return false;
+    }
+    return true;
+}
+
+bool
+PPX_Output::Equals(std::string &log, const PPX_Output &other)
+{
+    bool ret = true;
+    std::stringstream out;
+
+    if (status != other.status) {
+       out << "return status: " << std::boolalpha << status << " vs " <<
+           other.status << "\n";
+       ret = false;
+    }
+
+    if (events.Count() != other.events.Count()) {
+       out << "event count: " << events.Count() << " vs " <<
+           other.events.Count() << "\n";
+       ret = false;
+    } else {
+       for (int i = 0; i < events.Count(); ++i) {
+           if (!point_events_equal(other.events[i], events[i])) {
+               out << "event arrays don't match\n";
+               ret = false;
+               break;
+           }
+       }
+    }
+
+    log = out.str();
+
+    return ret;
+}
+
+void
+test_intersection(PPX_Input in, PPX_Output expected_out)
+{
+    PPX_Output out;
+
+    out.events = in.events;
+
+    if (in.default_tol) {
+       out.status = ON_Intersect(in.ptA, in.ptB, out.events);
+    } else {
+       out.status = ON_Intersect(in.ptA, in.ptB, out.events, in.tol);
+    }
+
+    std::string err_msg;
+    if (!expected_out.Equals(err_msg, out)) {
+       bu_exit(1, "Unexpected intersection result. Expected vs actual:\n%s",
+               err_msg.c_str());
+    }
+}
+
+static ON_PX_EVENT
+ppx_point_event(ON_3dPoint ptA, ON_3dPoint ptB)
+{
+    ON_PX_EVENT event;
+    event.m_type = ON_PX_EVENT::ppx_point;
+    event.m_A = ptA;
+    event.m_B = ptB;
+    event.m_b = ON_2dPoint(0.0, 0.0);
+    event.m_Mid = (ptA + ptB) * 0.5;
+    event.m_radius = ptA.DistanceTo(ptB) * 0.5;
+    return event;
+}
+
+static void
+test_equal_points(ON_3dPoint pt)
+{
+    ON_ClassArray<ON_PX_EVENT> events;
+    events.Append(ppx_point_event(pt, pt));
+
+    PPX_Output expected_output;
+    expected_output.status = true;
+    expected_output.events = events;
+
+    PPX_Input input;
+    input.ptA = input.ptB = pt;
+    input.default_tol = true;
+
+    test_intersection(input, expected_output);
+}
+
+static void
+do_equal_point_tests(void)
+{
+    std::vector<double> coord_vals;
+    coord_vals.push_back(-COORD_MAG_MAX);
+    coord_vals.push_back(-INTERSECTION_TOL);
+    coord_vals.push_back(0.0);
+    coord_vals.push_back(INTERSECTION_TOL);
+    coord_vals.push_back(COORD_MAG_MAX);
+
+    for (size_t i = 0; i < coord_vals.size(); ++i) {
+       for (size_t j = 0; j < coord_vals.size(); ++j) {
+           for (size_t k = 0; k < coord_vals.size(); ++k) {
+               ON_3dPoint test_pt(coord_vals[i], coord_vals[j],
+                       coord_vals[k]);
+
+               test_equal_points(test_pt);
+           }
+       }
+    }
+}
+
+int
+main(int UNUSED(argc), const char *argv[])
+{
+    bu_setprogname(argv[0]);
+
+    do_equal_point_tests();
+
+    return 0;
+}
+
+// Local Variables:
+// tab-width: 8
+// mode: C++
+// c-basic-offset: 4
+// indent-tabs-mode: t
+// c-file-style: "stroustrup"
+// End:
+// ex: shiftwidth=4 tabstop=8

Modified: brlcad/branches/bioh/src/libged/analyze/CMakeLists.txt
===================================================================
--- brlcad/branches/bioh/src/libged/analyze/CMakeLists.txt      2020-10-01 
13:13:00 UTC (rev 77302)
+++ brlcad/branches/bioh/src/libged/analyze/CMakeLists.txt      2020-10-01 
13:15:27 UTC (rev 77303)
@@ -6,9 +6,20 @@
   ${GED_INCLUDE_DIRS}
   )
 
+set(analyze_srcs
+  analyze.cpp
+  arb8.cpp
+  arbn.cpp
+  ars.cpp
+  superell.cpp
+  sketch.cpp
+  util.cpp
+  op_pnts_vol.cpp
+  )
+
 add_definitions(-DGED_PLUGIN)
-ged_plugin_library(ged-analyze SHARED analyze.c)
-target_link_libraries(ged-analyze libged libbu)
+ged_plugin_library(ged-analyze SHARED ${analyze_srcs})
+target_link_libraries(ged-analyze libged libanalyze libbu)
 set_property(TARGET ged-analyze APPEND PROPERTY COMPILE_DEFINITIONS 
BRLCADBUILD HAVE_CONFIG_H)
 VALIDATE_STYLE(ged-analyze analyze.c)
 PLUGIN_SETUP(ged-analyze ged)
@@ -15,7 +26,8 @@
 
 CMAKEFILES(
   CMakeLists.txt
-  analyze.c
+  ${analyze_srcs}
+  ged_analyze.h
   )
 
 # Local Variables:

Deleted: brlcad/branches/bioh/src/libged/analyze/analyze.c
===================================================================
--- brlcad/branches/bioh/src/libged/analyze/analyze.c   2020-10-01 13:13:00 UTC 
(rev 77302)
+++ brlcad/branches/bioh/src/libged/analyze/analyze.c   2020-10-01 13:15:27 UTC 
(rev 77303)
@@ -1,1341 +0,0 @@
-/*                          A N A L Y Z E . C
- * BRL-CAD
- *
- * Copyright (c) 1985-2020 United States Government as represented by
- * the U.S. Army Research Laboratory.
- *
- * This program is free software; you can redistribute it and/or
- * modify it under the terms of the GNU Lesser General Public License
- * version 2.1 as published by the Free Software Foundation.
- *
- * This program is distributed in the hope that it will be useful, but
- * WITHOUT ANY WARRANTY; without even the implied warranty of
- * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
- * Lesser General Public License for more details.
- *
- * You should have received a copy of the GNU Lesser General Public
- * License along with this file; see the file named COPYING for more
- * information.
- */
-/** @file libged/analyze.c
- *
- * The analyze command.
- *
- */
-
-#include "common.h"
-
-#include <math.h>
-#include <string.h>
-#include <assert.h>
-
-#include "vmath.h"
-#include "bn.h"
-#include "bg/polygon.h"
-#include "rt/arb_edit.h"
-#include "raytrace.h"
-#include "rt/geom.h"
-
-#include "../ged_private.h"
-
-/**
- * TODO: primitives that still need implementing
- * ehy
- * metaball
- * nmg
- */
-
-/* Conversion factor for Gallons to cubic millimeters */
-#define GALLONS_TO_MM3 3785411.784
-
-
-/* ARB face printout array */
-static const int prface[5][6] = {
-    {123, 124, 234, 134, -111, -111},          /* ARB4 */
-    {1234, 125, 235, 345, 145, -111},          /* ARB5 */
-    {1234, 2365, 1564, 512, 634, -111},                /* ARB6 */
-    {1234, 567, 145, 2376, 1265, 4375},                /* ARB7 */
-    {1234, 5678, 1584, 2376, 1265, 4378},      /* ARB8 */
-};
-
-
-/* edge definition array */
-static const int nedge[5][24] = {
-    {0, 1, 1, 2, 2, 0, 0, 3, 3, 2, 1, 3, -1, -1, -1, -1, -1, -1, -1, -1, -1, 
-1, -1, -1},   /* ARB4 */
-    {0, 1, 1, 2, 2, 3, 0, 3, 0, 4, 1, 4, 2, 4, 3, 4, -1, -1, -1, -1, -1, -1, 
-1, -1},       /* ARB5 */
-    {0, 1, 1, 2, 2, 3, 0, 3, 0, 4, 1, 4, 2, 5, 3, 5, 4, 5, -1, -1, -1, -1, -1, 
-1},         /* ARB6 */
-    {0, 1, 1, 2, 2, 3, 0, 3, 0, 4, 3, 4, 1, 5, 2, 6, 4, 5, 5, 6, 4, 6, -1, 
-1},             /* ARB7 */
-    {0, 1, 1, 2, 2, 3, 0, 3, 0, 4, 4, 5, 1, 5, 5, 6, 6, 7, 4, 7, 3, 7, 2, 6},  
             /* ARB8 */
-};
-
-
-/* contains information used to analyze a polygonal face */
-struct poly_face
-{
-    char label[5];
-    size_t npts;
-    point_t *pts;
-    plane_t plane_eqn;
-    fastf_t area;
-};
-
-
-#define POLY_FACE_INIT_ZERO { { 0, 0, 0, 0, 0 }, 0, NULL, HINIT_ZERO, 0.0 }
-
-#define ADD_PT(face, pt) do { VMOVE((face).pts[(face).npts], (pt)); 
(face).npts++; } while (0)
-
-/* structures and subroutines for analyze pretty printing */
-
-#define FBUFSIZ 100
-#define NFIELDS 9
-#define NOT_A_PLANE -1
-typedef struct row_field
-{
-    int nchars;
-    char buf[FBUFSIZ];
-} field_t;
-
-typedef struct table_row
-{
-    int nfields;
-    field_t fields[NFIELDS];
-} row_t;
-
-typedef struct table
-{
-    int nrows;
-    row_t *rows;
-} table_t;
-
-void get_dashes(field_t *f, const int ndashes)
-{
-    int i;
-    f->buf[0] = '\0';
-    for (i = 0; i < ndashes; ++i) {
-       bu_strlcat(f->buf, "-", FBUFSIZ);
-    }
-    f->nchars = ndashes;
-}
-
-
-void print_volume_table(struct ged *gedp
-                       , const fastf_t tot_vol
-                       , const fastf_t tot_area
-                       , const fastf_t tot_gallons
-    )
-{
-
-/* table format
-
-   +------------------------------------+
-   | Volume       = 7999999999.99999905 |
-   | Surface Area =   24000000.00000000 |
-   | Gallons      =       2113.37641887 |
-   +------------------------------------+
-
-*/
-    /* track actual table column widths */
-    /* this table has 1 column (plus a name column) */
-    int maxwidth[2] = {0, 0};
-    field_t dashes;
-    char* fnames[3] = {"Volume",
-                      "Surface Area",
-                      "Gallons"};
-    int indent = 4; /* number spaces to indent the table */
-    int table_width_chars;
-    table_t table;
-    int i, nd, field;
-
-    table.nrows = 3;
-    table.rows = (row_t *)bu_calloc(3, sizeof(row_t), "print_volume_table: 
rows");
-    for (i = 0; i < table.nrows; ++i) {
-       fastf_t val = 0.0;
-
-       /* field 0 */
-       field = 0;
-       table.rows[i].fields[0].nchars = 
snprintf(table.rows[i].fields[field].buf, FBUFSIZ, "%s",
-                                                 fnames[i]);
-       if (maxwidth[field] < table.rows[i].fields[field].nchars)
-           maxwidth[field] = table.rows[i].fields[field].nchars;
-
-       if (i == 0) {
-           val = tot_vol;
-       } else if (i == 1) {
-           val = tot_area;
-       } else if (i == 2) {
-           val = tot_gallons;
-       }
-
-       /* field 1 */
-       field = 1;
-       if (val < 0) {
-           table.rows[i].fields[1].nchars = 
snprintf(table.rows[i].fields[field].buf, FBUFSIZ, "COULD NOT DETERMINE");
-       } else {
-           table.rows[i].fields[1].nchars = 
snprintf(table.rows[i].fields[field].buf, FBUFSIZ, "%10.8f", val);
-       }
-       if (maxwidth[field] < table.rows[i].fields[field].nchars)
-           maxwidth[field] = table.rows[i].fields[field].nchars;
-    }
-
-    /* get total table width */
-    table_width_chars  = maxwidth[0] + maxwidth[1];
-    table_width_chars += 2 + 2; /* 2 chars at each end of a row */
-    table_width_chars += 3; /* ' = ' between the two fields of a row */
-
-    /* newline following previous table */
-    bu_vls_printf(gedp->ged_result_str, "\n");
-
-    /* header row 1 */
-    nd = table_width_chars - 4;
-    get_dashes(&dashes, nd);
-    bu_vls_printf(gedp->ged_result_str, "%-*.*s+-%-*.*s-+\n",
-                 indent, indent, " ",
-                 nd, nd, dashes.buf);
-
-    /* the three data rows */
-    for (i = 0; i < table.nrows; ++i) {
-       bu_vls_printf(gedp->ged_result_str, "%-*.*s| %-*.*s = %*.*s |\n",
-                     indent, indent, " ",
-                     maxwidth[0], maxwidth[0], table.rows[i].fields[0].buf,
-                     maxwidth[1], maxwidth[1], table.rows[i].fields[1].buf);
-    }
-
-    /* closing table row */
-    bu_vls_printf(gedp->ged_result_str, "%-*.*s+-%-*.*s-+\n",
-                 indent, indent, " ",
-                 nd, nd, dashes.buf);
-    bu_free((char *)table.rows, "print_volume_table: rows");
-}
-
-
-void print_edges_table(struct ged *gedp, table_t *table)
-{
-
-/* table header
-
-   
+--------------------+--------------------+--------------------+--------------------+
-   | EDGE          LEN  | EDGE          LEN  | EDGE          LEN  | EDGE       
   LEN  |
-   
+--------------------+--------------------+--------------------+--------------------+
-
-*/
-
-    int i;
-    int tcol, nd, nrow, nrows;
-    int maxwidth[] = {0, 0, 0,
-                     0, 0, 0,
-                     0, 0};
-    int indent = 2;
-    field_t dashes;
-    char EDGE[] = {"EDGE"};
-    int elen    = strlen(EDGE);
-    char LEN[]  = {"LENGTH"};
-    int llen    = strlen(LEN);
-    char buf[FBUFSIZ];
-
-    /* put four edges per row making 8 columns */
-    /* this table has 8 columns per row: 2 columns per edge; 4 edges per row */
-
-    /* collect max table column widths */
-    tcol = 0;
-    for (i = 0; i < table->nrows; ++i) {
-       /* field 0 */
-       int field = 0;
-       if (maxwidth[tcol] < table->rows[i].fields[field].nchars)
-           maxwidth[tcol] = table->rows[i].fields[field].nchars;
-       if (maxwidth[tcol] < elen)
-           maxwidth[tcol] = elen;
-
-       /* field 1 */
-       field = 1;
-       if (maxwidth[tcol+1] < table->rows[i].fields[field].nchars)
-           maxwidth[tcol+1] = table->rows[i].fields[field].nchars;
-       if (maxwidth[tcol] < llen)
-           maxwidth[tcol] = llen;
-
-       /* iterate on columns */
-       tcol += 2;
-       tcol = tcol > 6 ? 0 : tcol;
-    }
-
-    /* header row 1 */
-    /* print dashes in 4 sets */
-    nd = maxwidth[0] + maxwidth[1] + 3; /* 1 space between numbers and one at 
each end */
-    get_dashes(&dashes, nd);
-    bu_vls_printf(gedp->ged_result_str, "%-*.*s+%-*.*s",

@@ Diff output truncated at 100000 characters. @@
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