Revision: 76852
          http://sourceforge.net/p/brlcad/code/76852
Author:   starseeker
Date:     2020-08-19 22:55:01 +0000 (Wed, 19 Aug 2020)
Log Message:
-----------
Checkpoint

Modified Paths:
--------------
    brlcad/branches/analyze_cmd/src/libged/analyze/CMakeLists.txt
    brlcad/branches/analyze_cmd/src/libged/analyze/analyze.cpp
    brlcad/branches/analyze_cmd/src/libged/analyze/ged_analyze.h
    brlcad/branches/analyze_cmd/src/libged/pnts_util.c
    brlcad/branches/analyze_cmd/src/libged/pnts_util.h

Added Paths:
-----------
    brlcad/branches/analyze_cmd/src/libged/analyze/op_pnts_vol.cpp

Modified: brlcad/branches/analyze_cmd/src/libged/analyze/CMakeLists.txt
===================================================================
--- brlcad/branches/analyze_cmd/src/libged/analyze/CMakeLists.txt       
2020-08-19 17:50:31 UTC (rev 76851)
+++ brlcad/branches/analyze_cmd/src/libged/analyze/CMakeLists.txt       
2020-08-19 22:55:01 UTC (rev 76852)
@@ -14,6 +14,7 @@
   superell.cpp
   sketch.cpp
   util.cpp
+  op_pnts_vol.cpp
   )
 
 add_definitions(-DGED_PLUGIN)

Modified: brlcad/branches/analyze_cmd/src/libged/analyze/analyze.cpp
===================================================================
--- brlcad/branches/analyze_cmd/src/libged/analyze/analyze.cpp  2020-08-19 
17:50:31 UTC (rev 76851)
+++ brlcad/branches/analyze_cmd/src/libged/analyze/analyze.cpp  2020-08-19 
22:55:01 UTC (rev 76852)
@@ -40,6 +40,10 @@
 #include "./ged_analyze.h"
 }
 
+#define DB_SOLID INT_MAX
+#define DB_NON_SOLID INT_MAX - 1
+
+
 #define HELPFLAG "--print-help"
 #define PURPOSEFLAG "--print-purpose"
 
@@ -48,9 +52,138 @@
     const struct bu_cmdtab *cmds = NULL;
     struct bu_opt_desc *gopts = NULL;
     int verbosity = 0;
+    std::map<std::pair<int, int>, op_func_ptr> *union_map;
+    std::map<std::pair<int, int>, op_func_ptr> *isect_map;
+    std::map<std::pair<int, int>, op_func_ptr> *subtr_map;
 };
 
 
+static struct _ged_analyze_info *
+_analyze_info_create()
+{
+    struct _ged_analyze_info *gc = new struct _ged_analyze_info;
+    gc->verbosity = 0;
+    gc->union_map = new std::map<std::pair<int, int>, op_func_ptr>;
+    gc->isect_map = new std::map<std::pair<int, int>, op_func_ptr>;
+    gc->subtr_map = new std::map<std::pair<int, int>, op_func_ptr>;
+
+
+    // Populate the maps with known pair analysis functions
+    (*gc->union_map)[std::make_pair(DB5_MINORTYPE_BRLCAD_PNTS, DB_SOLID)] = 
op_pnts_vol;
+    (*gc->isect_map)[std::make_pair(DB5_MINORTYPE_BRLCAD_PNTS, DB_SOLID)] = 
op_pnts_vol;
+    (*gc->subtr_map)[std::make_pair(DB5_MINORTYPE_BRLCAD_PNTS, DB_SOLID)] = 
op_pnts_vol;
+
+    return gc;
+}
+
+static void
+_analyze_info_destroy(struct _ged_analyze_info *s)
+{
+    delete[] s->union_map;
+    delete[] s->isect_map;
+    delete[] s->subtr_map;
+    delete[] s;
+}
+
+static bool
+db_solid_type(int type)
+{
+    switch (type) {
+       case DB5_MINORTYPE_BRLCAD_ARB8:
+       case DB5_MINORTYPE_BRLCAD_ARBN:
+       case DB5_MINORTYPE_BRLCAD_ARS:
+       case DB5_MINORTYPE_BRLCAD_BOT:
+       case DB5_MINORTYPE_BRLCAD_BREP:
+       case DB5_MINORTYPE_BRLCAD_BSPLINE:
+       case DB5_MINORTYPE_BRLCAD_CLINE:
+       case DB5_MINORTYPE_BRLCAD_COMBINATION:
+       case DB5_MINORTYPE_BRLCAD_DSP:
+       case DB5_MINORTYPE_BRLCAD_EBM:
+       case DB5_MINORTYPE_BRLCAD_EHY:
+       case DB5_MINORTYPE_BRLCAD_ELL:
+       case DB5_MINORTYPE_BRLCAD_EPA:
+       case DB5_MINORTYPE_BRLCAD_ETO:
+       case DB5_MINORTYPE_BRLCAD_EXTRUDE:
+       case DB5_MINORTYPE_BRLCAD_HALF:
+       case DB5_MINORTYPE_BRLCAD_HF:
+       case DB5_MINORTYPE_BRLCAD_HRT:
+       case DB5_MINORTYPE_BRLCAD_HYP:
+       case DB5_MINORTYPE_BRLCAD_METABALL:
+       case DB5_MINORTYPE_BRLCAD_NMG:
+       case DB5_MINORTYPE_BRLCAD_PARTICLE:
+       case DB5_MINORTYPE_BRLCAD_PIPE:
+       case DB5_MINORTYPE_BRLCAD_POLY:
+       case DB5_MINORTYPE_BRLCAD_REC:
+       case DB5_MINORTYPE_BRLCAD_REVOLVE:
+       case DB5_MINORTYPE_BRLCAD_RHC:
+       case DB5_MINORTYPE_BRLCAD_RPC:
+       case DB5_MINORTYPE_BRLCAD_SKETCH:
+       case DB5_MINORTYPE_BRLCAD_SPH:
+       case DB5_MINORTYPE_BRLCAD_SUBMODEL:
+       case DB5_MINORTYPE_BRLCAD_SUPERELL:
+       case DB5_MINORTYPE_BRLCAD_TGC:
+       case DB5_MINORTYPE_BRLCAD_TOR:
+       case DB5_MINORTYPE_BRLCAD_VOL:
+           return true;
+       case DB5_MINORTYPE_BRLCAD_ANNOT:
+       case DB5_MINORTYPE_BRLCAD_CONSTRAINT:
+       case DB5_MINORTYPE_BRLCAD_DATUM:
+       case DB5_MINORTYPE_BRLCAD_GRIP:
+       case DB5_MINORTYPE_BRLCAD_JOINT:
+       case DB5_MINORTYPE_BRLCAD_PNTS:
+       case DB5_MINORTYPE_BRLCAD_SCRIPT:
+       default:
+           return false;
+    };
+}
+
+static op_func_ptr
+_analyze_find_processor(struct _ged_analyze_info *s, db_op_t op, int t1, int 
t2)
+{
+    int type1 = t1;
+    int type2 = t2;
+    std::map<std::pair<int, int>, op_func_ptr> *omap;
+    switch (op) {
+       case DB_OP_UNION:
+           omap = s->union_map;
+           break;
+       case DB_OP_INTERSECT:
+           omap = s->isect_map;
+           break;
+       case DB_OP_SUBTRACT:
+           omap = s->subtr_map;
+           break;
+       default:
+           return NULL;
+    }
+
+    if (omap->find(std::make_pair(type1, type2)) != omap->end()) {
+       return (*omap)[std::make_pair(t1, t2)];
+    }
+
+    // If there isn't a specific type, see if there's a generic match for t2
+    type2 = (db_solid_type(t2)) ? DB_SOLID : DB_NON_SOLID;
+    if (omap->find(std::make_pair(type1, type2)) != omap->end()) {
+       return (*omap)[std::make_pair(t1, t2)];
+    }
+
+    // If there isn't a specific type, see if there's a generic match for t1
+    type1 = (db_solid_type(t1)) ? DB_SOLID : DB_NON_SOLID;
+    type2 = t2;
+    if (omap->find(std::make_pair(type1, type2)) != omap->end()) {
+       return (*omap)[std::make_pair(t1, t2)];
+    }
+    // If there isn't a match, see if there's a generic match for t1 and t2
+    type1 = (db_solid_type(t1)) ? DB_SOLID : DB_NON_SOLID;
+    type2 = (db_solid_type(t2)) ? DB_SOLID : DB_NON_SOLID;
+    if (omap->find(std::make_pair(type1, type2)) != omap->end()) {
+       return (*omap)[std::make_pair(t1, t2)];
+    }
+
+    // Nope, nothing
+    return NULL;
+}
+
 static int
 _analyze_cmd_msgs(void *cs, int argc, const char **argv, const char *us, const 
char *ps)
 {
@@ -202,7 +335,124 @@
     return GED_OK;
 }
 
+
 extern "C" int
+_analyze_cmd_intersect(void *bs, int argc, const char **argv)
+{
+    const char *usage_string = "analyze [options] intersect [-o out_obj] obj1 
obj2 <...>";
+    const char *purpose_string = "Intersect obj1 with obj2 and any subsequent 
objs";
+    if (_analyze_cmd_msgs(bs, argc, argv, usage_string, purpose_string)) {
+       return GED_OK;
+    }
+
+    struct _ged_analyze_info *gc = (struct _ged_analyze_info *)bs;
+    struct ged *gedp = gc->gedp;
+
+    argc--; argv++;
+    if (!argc) {
+       bu_vls_printf(gc->gedp->ged_result_str, "%s\n", usage_string);
+       return GED_ERROR;
+    }
+
+    GED_CHECK_DATABASE_OPEN(gedp, GED_ERROR);
+    GED_CHECK_ARGC_GT_0(gedp, argc, GED_ERROR);
+
+    /* initialize result */
+    bu_vls_trunc(gedp->ged_result_str, 0);
+
+    // See if we are going to output an object
+    int help = 0;
+    struct bu_vls oname = BU_VLS_INIT_ZERO;
+    struct bu_opt_desc d[3];
+    BU_OPT(d[0], "h", "help",    "",      NULL,        &help,  "Print help");
+    BU_OPT(d[1], "o", "output",  "name",  &bu_opt_vls, &oname, "Specify output 
object");
+    BU_OPT_NULL(d[2]);
+
+    int ac = bu_opt_parse(NULL, argc, argv, d);
+    if (help) {
+       bu_vls_printf(gc->gedp->ged_result_str, "%s\n", usage_string);
+       return GED_HELP;
+    }
+    if (ac < 2) {
+       bu_vls_printf(gc->gedp->ged_result_str, "%s\n", usage_string);
+       return GED_HELP;
+    }
+
+    long ret = 0;
+    const char *n1 = NULL;
+    const char *n2 = NULL;
+    const char *r1 = NULL;
+    const char *o1 = NULL;
+    const char *t1 = "tmp1";
+    const char *t2 = "tmp2";
+    /* use the names that were input */
+    for (int i = 1; i < argc; i++) {
+       struct rt_db_internal i1, i2;
+       if (i == 1) {
+           n1 = argv[0];
+           n2 = argv[i];
+           o1 = t1;
+           r1 = t2;
+       } else {
+           {
+               const char *av[3];
+               av[0] = "kill";
+               av[1] = "-f";
+               av[2] = r1;
+               ged_kill(gc->gedp, 3, (const char **)av);
+           }
+           const char *tmp = r1;
+           r1 = o1;
+           o1 = tmp;
+           n1 = o1;
+           n2 = argv[i];
+       }
+
+       struct directory *dp1 = db_lookup(gedp->ged_wdbp->dbip, n1, 
LOOKUP_NOISY);
+       struct directory *dp2 = db_lookup(gedp->ged_wdbp->dbip, n2, 
LOOKUP_NOISY);
+       GED_DB_GET_INTERNAL(gedp, &i1, dp1, bn_mat_identity, &rt_uniresource, 
GED_ERROR);
+       GED_DB_GET_INTERNAL(gedp, &i2, dp2, bn_mat_identity, &rt_uniresource, 
GED_ERROR);
+       op_func_ptr of = _analyze_find_processor(gc, DB_OP_INTERSECT, 
i1.idb_minor_type, i2.idb_minor_type);
+
+       if (of) {
+           ret = (*of)(o1, gc->gedp,  DB_OP_INTERSECT, n1, n2);
+           if (ret == -1) {
+               {
+                   struct bu_vls tmpstr = BU_VLS_INIT_ZERO;
+                   bu_vls_sprintf(&tmpstr, "%s", 
bu_vls_cstr(gedp->ged_result_str));
+                   const char *av[3];
+                   av[0] = "kill";
+                   av[1] = "-f";
+                   av[2] = o1;
+                   ged_kill(gc->gedp, 3, (const char **)av);
+                   bu_vls_sprintf(gedp->ged_result_str, "%s", 
bu_vls_cstr(&tmpstr));
+               }
+               return GED_ERROR;
+           }
+       }
+    }
+
+    if (bu_vls_strlen(&oname)) {
+       const char *av[3];
+       av[0] = "mv";
+       av[1] = o1;
+       av[2] = bu_vls_cstr(&oname);
+       ged_move(gc->gedp, 3, (const char **)av);
+    } else {
+       const char *av[3];
+       av[0] = "kill";
+       av[1] = "-f";
+       av[2] = o1;
+       ged_kill(gc->gedp, 3, (const char **)av);
+    }
+
+    bu_vls_sprintf(gedp->ged_result_str, "%ld", ret);
+
+    return GED_OK;
+}
+
+
+extern "C" int
 _analyze_cmd_help(void *bs, int argc, const char **argv)
 {
     struct _ged_analyze_info *gc = (struct _ged_analyze_info *)bs;
@@ -252,6 +502,7 @@
 
 const struct bu_cmdtab _analyze_cmds[] = {
       { "summarize",            _analyze_cmd_summarize},
+      { "intersect",            _analyze_cmd_intersect},
       { (char *)NULL,      NULL}
   };
 
@@ -260,13 +511,13 @@
 ged_analyze_core(struct ged *gedp, int argc, const char *argv[])
 {
     int help = 0;
-    struct _ged_analyze_info gc;
-    gc.gedp = gedp;
-    gc.cmds = _analyze_cmds;
-    gc.verbosity = 0;
+    struct _ged_analyze_info *gc = _analyze_info_create();
+    gc->gedp = gedp;
+    gc->cmds = _analyze_cmds;
 
     // Sanity
     if (UNLIKELY(!gedp || !argc || !argv)) {
+       _analyze_info_destroy(gc);
        return GED_ERROR;
     }
 
@@ -275,14 +526,15 @@
 
     // See if we have any high level options set
     struct bu_opt_desc d[3];
-    BU_OPT(d[0], "h", "help",    "",      NULL,                 &help,         
"Print help");
-    BU_OPT(d[1], "v", "verbose", "",      NULL,                 &gc.verbosity, 
"Verbose output");
+    BU_OPT(d[0], "h", "help",    "",  NULL, &help,          "Print help");
+    BU_OPT(d[1], "v", "verbose", "",  NULL, &gc->verbosity, "Verbose output");
     BU_OPT_NULL(d[2]);
 
-    gc.gopts = d;
+    gc->gopts = d;
 
     if (argc == 1) {
        _analyze_cmd_help(&gc, 0, NULL);
+       _analyze_info_destroy(gc);
        return GED_OK;
     }
 
@@ -307,9 +559,11 @@
        } else {
            _analyze_cmd_help(&gc, 0, NULL);
        }
+       _analyze_info_destroy(gc);
        return GED_OK;
     }
 
+
     // Jump the processing past any options specified. If we don't have a
     // subcommand, assume all args are geometry objects and the command mode is
     // summarize. This will get us the old behavior, except in the case where
@@ -325,11 +579,13 @@
 
     int ret;
     if (bu_cmd(_analyze_cmds, argc, argv, 0, (void *)&gc, &ret) == BRLCAD_OK) {
+       _analyze_info_destroy(gc);
        return ret;
     } else {
        bu_vls_printf(gedp->ged_result_str, "subcommand %s not defined", 
argv[0]);
     }
 
+    _analyze_info_destroy(gc);
     return GED_ERROR;
 }
 

Modified: brlcad/branches/analyze_cmd/src/libged/analyze/ged_analyze.h
===================================================================
--- brlcad/branches/analyze_cmd/src/libged/analyze/ged_analyze.h        
2020-08-19 17:50:31 UTC (rev 76851)
+++ brlcad/branches/analyze_cmd/src/libged/analyze/ged_analyze.h        
2020-08-19 22:55:01 UTC (rev 76852)
@@ -29,6 +29,7 @@
 #include "common.h"
 
 #include "vmath.h"
+#include "rt/op.h"
 #include "./ged/defines.h"
 
 __BEGIN_DECLS
@@ -111,6 +112,35 @@
 GED_EXPORT extern void
 analyze_general(struct ged *gedp, const struct rt_db_internal *ip);
 
+
+
+/**
+ * Functions for performing union/intersection/subtraction analysis operations
+ * on various type combinations.
+ *
+ * output_obj is optional.  If non-NULL, it is the name used to produce a new
+ * geometry database object with the results of the operation (if any).
+ *
+ * The trivial case would be an op_vol_vol that takes two csg solids or combs
+ * and returns a new implicit comb with them unioned (always), intersected (if
+ * there is overlap) or subtracted (if there is overlap).
+ *
+ * More interesting are cases like op_pnts_vol that will produce new pnts
+ * objects based on boolean set operation analysis.
+ */
+
+typedef long (*op_func_ptr)(const char *, struct ged *, db_op_t, const char *, 
const char *);
+
+GED_EXPORT extern long
+op_pnts_vol(
+       const char *output_obj,
+       struct ged *gedp,
+       db_op_t op,
+       const char *pnt_obj,
+       const char *vol_obj
+       );
+
+
 __END_DECLS
 
 #endif /* LIBGED_ANALYZE_GED_PRIVATE_H */

Added: brlcad/branches/analyze_cmd/src/libged/analyze/op_pnts_vol.cpp
===================================================================
--- brlcad/branches/analyze_cmd/src/libged/analyze/op_pnts_vol.cpp              
                (rev 0)
+++ brlcad/branches/analyze_cmd/src/libged/analyze/op_pnts_vol.cpp      
2020-08-19 22:55:01 UTC (rev 76852)
@@ -0,0 +1,383 @@
+/*                 O P _ P N T S _ V O L . C P P
+ * BRL-CAD
+ *
+ * Copyright (c) 2020 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 op_pnts_vol.cpp
+ *
+ * Test all points in a pnts object for inside/outside status against
+ * a CSG volume.
+ *
+ */
+
+#include "common.h"
+
+extern "C" {
+#include <stdlib.h>
+#include <ctype.h>
+#include <string.h>
+}
+
+extern "C" {
+#include "rt/geom.h"
+#include "analyze.h"
+#include "../ged_private.h"
+#include "../pnts_util.h"
+#include "./ged_analyze.h"
+}
+
+static void
+_tgc_hack_fix(struct partition *part, struct soltab *stp) {
+    /* hack fix for bad tgc surfaces - avoids a logging crash, which is 
probably something else altogether... */
+    if (bu_strncmp("rec", stp->st_meth->ft_label, 3) == 0 || bu_strncmp("tgc", 
stp->st_meth->ft_label, 3) == 0) {
+
+        /* correct invalid surface number */
+        if (part->pt_inhit->hit_surfno < 1 || part->pt_inhit->hit_surfno > 3) {
+            part->pt_inhit->hit_surfno = 2;
+        }
+        if (part->pt_outhit->hit_surfno < 1 || part->pt_outhit->hit_surfno > 
3) {
+            part->pt_outhit->hit_surfno = 2;
+        }
+    }
+}
+
+
+static int
+in_out_hit(struct application *ap, struct partition *partH, struct seg 
*UNUSED(segs))
+{
+    struct partition *part = partH->pt_forw;
+    struct soltab *stp = part->pt_inseg->seg_stp;
+
+    int *ret = (int *)(ap->a_uptr);
+
+    RT_CK_APPLICATION(ap);
+
+    _tgc_hack_fix(part, stp);
+
+    // Any partition containing the test point will have a hit distance less 
than
+    // or at the test point.  If we find such a partition, set the flag.
+    if (part->pt_inhit->hit_dist < 0) {
+        (*ret) = -1;
+    }
+
+    // Differentiate approximately on the surface via the flag value, in case
+    // that's of interest.
+    if (NEAR_ZERO(part->pt_inhit->hit_dist, VUNITIZE_TOL)) {
+        (*ret) = 1;
+    }
+
+    // Test point not on the partition
+    return 0;
+}
+
+static int
+in_out_miss(struct application *UNUSED(ap))
+{
+    return 0;
+}
+
+// Return 0 if not inside, 1 if (approximately) on and -1 if inside the volume.
+static int
+_pnt_in_vol(point_t *p, struct application *ap)
+{
+    int inside_flag = 0;
+    int (*a_hit)(struct application *, struct partition *, struct seg *);
+    int (*a_miss)(struct application *);
+    void *uptr_stash;
+
+    vect_t pz;
+    VSET(pz,  0,  0,  1);
+
+    /* reuse existing application, just cache pre-existing hit routines and
+     * substitute our own */
+    a_hit = ap->a_hit;
+    a_miss = ap->a_miss;
+    uptr_stash = ap->a_uptr;
+
+    ap->a_hit = in_out_hit;
+    ap->a_miss = in_out_miss;
+
+    VMOVE(ap->a_ray.r_pt, *p);
+
+    ap->a_uptr = &inside_flag;
+    VMOVE(ap->a_ray.r_dir, pz);
+    (void)rt_shootray(ap);
+
+    /* restore application */
+    ap->a_hit = a_hit;
+    ap->a_miss = a_miss;
+    ap->a_uptr = uptr_stash;
+
+    return inside_flag;
+}
+
+
+extern "C" long
+op_pnts_vol(
+       const char *output_pnts_obj,
+       struct ged *gedp,
+       db_op_t op,
+       const char *pnts_obj,
+       const char *vol_obj
+       )
+{
+    struct pnt *pstd, *pstdl = NULL;
+    struct pnt_color *pc, *pcl = NULL;
+    struct pnt_scale *ps, *psl = NULL;
+    struct pnt_normal *pn, *pnl = NULL;
+    struct pnt_color_scale *pcs, *pcsl = NULL;
+    struct pnt_color_normal *pcn, *pcnl = NULL;
+    struct pnt_scale_normal *psn, *psnl = NULL;
+    struct pnt_color_scale_normal *pcsn, *pcsnl = NULL;
+    void *npnt = NULL;
+    int iostat = 0;
+    struct rt_db_internal internal;
+    long pntcnt = 0;
+    struct rt_pnts_internal *opnts = NULL;
+
+    // If we're supposed to make an output object, don't do anything
+    // until we're sure the way is clear.
+    if (output_pnts_obj) {
+       struct directory *odp = db_lookup(gedp->ged_wdbp->dbip, pnts_obj, 
LOOKUP_QUIET);
+       if (odp != RT_DIR_NULL) {
+           bu_vls_printf(gedp->ged_result_str, "%s already exists, aborting", 
output_pnts_obj);
+           return -1;
+       }
+    }
+
+    // Unpack the points object
+    struct directory *dp = db_lookup(gedp->ged_wdbp->dbip, pnts_obj, 
LOOKUP_QUIET);
+    struct rt_db_internal tpnts_intern;
+    GED_DB_GET_INTERNAL(gedp, &tpnts_intern, dp, bn_mat_identity, 
&rt_uniresource, GED_ERROR);
+    if (tpnts_intern.idb_minor_type != DB5_MINORTYPE_BRLCAD_PNTS) {
+       bu_vls_printf(gedp->ged_result_str, "%s is not a pnts object, 
aborting", pnts_obj);
+       rt_db_free_internal(&tpnts_intern);
+       return -1;
+    }
+    struct rt_pnts_internal *pnts = (struct rt_pnts_internal 
*)tpnts_intern.idb_ptr;
+    RT_PNTS_CK_MAGIC(pnts);
+
+    // Since we need to verify type info about vol_obj, look it up
+    if (vol_obj) {
+       dp = db_lookup(gedp->ged_wdbp->dbip, vol_obj, LOOKUP_QUIET);
+    }
+    // If we're missing the volume object, union or subtraction result
+    // in the point set being unchanged.
+    if (!dp && (op == DB_OP_UNION || op == DB_OP_SUBTRACT)) {
+       if (output_pnts_obj) {
+           const char *av[3];
+           av[0] = "copy";
+           av[1] = pnts_obj;
+           av[2] = output_pnts_obj;
+           (void)ged_copy(gedp, 3, (const char **)av);
+       }
+       rt_db_free_internal(&tpnts_intern);
+       return pnts->count;
+    }
+    // Intersecting with nothing yields nothing
+    if (!dp && op == DB_OP_INTERSECT) {
+       rt_db_free_internal(&tpnts_intern);
+       return 0;
+    }
+
+    /* Verify the object supplied as the volume object has
+     * non non-volumetric object types in its hierarchy.  If
+     * there is such an object, abandon the test.  */
+    const char *tfilter = "! -type solid";
+    if (db_search(NULL, DB_SEARCH_QUIET, tfilter, 1, &dp, 
gedp->ged_wdbp->dbip, NULL) > 0) {
+       bu_vls_printf(gedp->ged_result_str, "Non-solid object found in %s, 
aborting\n", vol_obj);
+       rt_db_free_internal(&tpnts_intern);
+       return -1;
+    }
+
+    /* For the volume object, we need to raytrace it */
+    struct application *ap;
+    struct resource *resp;
+    struct rt_i *rtip;
+    size_t ncpus;
+    BU_GET(ap, struct application);
+    RT_APPLICATION_INIT(ap);
+    BU_GET(resp, struct resource);
+    rtip = rt_new_rti(gedp->ged_wdbp->dbip);
+    rt_init_resource(resp, 0, rtip);
+    ap->a_rt_i = rtip;
+    ap->a_resource = resp;
+    ap->a_onehit = 1;
+    ap->a_hit = NULL;
+    ap->a_miss = NULL;
+    ap->a_overlap = NULL;
+    ap->a_logoverlap = rt_silent_logoverlap;
+    if ((rt_gettree(rtip, vol_obj) < 0)) {
+       pntcnt = -1;
+       goto pnts_internal_memfree;
+    }
+    ncpus = bu_avail_cpus();
+    rt_prep_parallel(rtip, ncpus);
+
+    /* For the output, make a new pnts object */
+    if (output_pnts_obj) {
+       RT_DB_INTERNAL_INIT(&internal);
+       internal.idb_major_type = DB5_MAJORTYPE_BRLCAD;
+       internal.idb_type = ID_PNTS;
+       internal.idb_meth = &OBJ[ID_PNTS];
+       BU_ALLOC(internal.idb_ptr, struct rt_pnts_internal);
+       opnts = (struct rt_pnts_internal *) internal.idb_ptr;
+       opnts->magic = RT_PNTS_INTERNAL_MAGIC;
+       opnts->scale = pnts->scale;
+       opnts->type = pnts->type;
+       opnts->point = _ged_pnts_new_pnt(pnts->type);
+       _ged_pnts_init_head_pnt(opnts);
+    }
+
+    switch(pnts->type) {
+       case RT_PNT_TYPE_PNT:
+           pstdl = (struct pnt *)pnts->point;
+           for (BU_LIST_FOR(pstd, pnt, &(pstdl->l))) {
+               iostat = _pnt_in_vol(&(pstd->v), ap);
+               if ((op == DB_OP_INTERSECT && iostat) || (op == DB_OP_SUBTRACT 
&& !iostat)) {
+                   if (output_pnts_obj) {
+                       npnt = _ged_pnts_dup((void *)pstd, RT_PNT_TYPE_PNT);
+                       _ged_pnts_add(opnts, npnt);
+                   }
+                   pntcnt++;
+               }
+           }
+           break;
+       case RT_PNT_TYPE_COL:
+           pcl = (struct pnt_color *)pnts->point;
+           for (BU_LIST_FOR(pc, pnt_color, &(pcl->l))) {
+               iostat = _pnt_in_vol(&(pc->v), ap);
+               if ((op == DB_OP_INTERSECT && iostat) || (op == DB_OP_SUBTRACT 
&& !iostat)) {
+                   if (output_pnts_obj) {
+                       npnt = _ged_pnts_dup((void *)pc, RT_PNT_TYPE_COL);
+                       _ged_pnts_add(opnts, npnt);
+                   }
+                   pntcnt++;
+               }
+           }
+           break;
+       case RT_PNT_TYPE_SCA:
+           psl = (struct pnt_scale *)pnts->point;
+           for (BU_LIST_FOR(ps, pnt_scale, &(psl->l))) {
+               iostat = _pnt_in_vol(&(ps->v), ap);
+               if ((op == DB_OP_INTERSECT && iostat) || (op == DB_OP_SUBTRACT 
&& !iostat)) {
+                   if (output_pnts_obj) {
+                       npnt = _ged_pnts_dup((void *)ps, RT_PNT_TYPE_SCA);
+                       _ged_pnts_add(opnts, npnt);
+                   }
+                   pntcnt++;
+               }
+           }
+           break;
+       case RT_PNT_TYPE_NRM:
+           pnl = (struct pnt_normal *)pnts->point;
+           for (BU_LIST_FOR(pn, pnt_normal, &(pnl->l))) {
+               iostat = _pnt_in_vol(&(pn->v), ap);
+               if ((op == DB_OP_INTERSECT && iostat) || (op == DB_OP_SUBTRACT 
&& !iostat)) {
+                   if (output_pnts_obj) {
+                       npnt = _ged_pnts_dup((void *)pn, RT_PNT_TYPE_NRM);
+                       _ged_pnts_add(opnts, npnt);
+                   }
+                   pntcnt++;
+               }
+           }
+           break;
+       case RT_PNT_TYPE_COL_SCA:
+           pcsl = (struct pnt_color_scale *)pnts->point;
+           for (BU_LIST_FOR(pcs, pnt_color_scale, &(pcsl->l))) {
+               iostat = _pnt_in_vol(&(pcs->v), ap);
+               if ((op == DB_OP_INTERSECT && iostat) || (op == DB_OP_SUBTRACT 
&& !iostat)) {
+                   if (output_pnts_obj) {
+                       npnt = _ged_pnts_dup((void *)pcs, RT_PNT_TYPE_COL_SCA);
+                       _ged_pnts_add(opnts, npnt);
+                   }
+                   pntcnt++;
+               }
+           }
+           break;
+       case RT_PNT_TYPE_COL_NRM:
+           pcnl = (struct pnt_color_normal *)pnts->point;
+           for (BU_LIST_FOR(pcn, pnt_color_normal, &(pcnl->l))) {
+               iostat = _pnt_in_vol(&(pcn->v), ap);
+               if ((op == DB_OP_INTERSECT && iostat) || (op == DB_OP_SUBTRACT 
&& !iostat)) {
+                   if (output_pnts_obj) {
+                       npnt = _ged_pnts_dup((void *)pcn, RT_PNT_TYPE_COL_NRM);
+                       _ged_pnts_add(opnts, npnt);
+                   }
+                   pntcnt++;
+               }
+           }
+           break;
+       case RT_PNT_TYPE_SCA_NRM:
+           psnl = (struct pnt_scale_normal *)pnts->point;
+           for (BU_LIST_FOR(psn, pnt_scale_normal, &(psnl->l))) {
+               iostat = _pnt_in_vol(&(psn->v), ap);
+               if ((op == DB_OP_INTERSECT && iostat) || (op == DB_OP_SUBTRACT 
&& !iostat)) {
+                   if (output_pnts_obj) {
+                       npnt = _ged_pnts_dup((void *)psn, RT_PNT_TYPE_SCA_NRM);
+                       _ged_pnts_add(opnts, npnt);
+                   }
+                   pntcnt++;
+               }
+           }
+           break;
+       case RT_PNT_TYPE_COL_SCA_NRM:
+           pcsnl = (struct pnt_color_scale_normal *)pnts->point;
+           for (BU_LIST_FOR(pcsn, pnt_color_scale_normal, &(pcsnl->l))) {
+               iostat = _pnt_in_vol(&(pcsn->v), ap);
+               if ((op == DB_OP_INTERSECT && iostat) || (op == DB_OP_SUBTRACT 
&& !iostat)) {
+                   if (output_pnts_obj) {
+                       npnt = _ged_pnts_dup((void *)pcsn, 
RT_PNT_TYPE_COL_SCA_NRM);
+                       _ged_pnts_add(opnts, npnt);
+                   }
+                   pntcnt++;
+               }
+           }
+           break;
+       default:
+           bu_vls_printf(gedp->ged_result_str, "Unknown point type in object, 
aborting\n");
+           pntcnt = -1;
+           goto pnts_internal_memfree;
+    };
+
+    if (output_pnts_obj) {
+       opnts->count = pntcnt;
+       GED_DB_DIRADD(gedp, dp, output_pnts_obj, RT_DIR_PHONY_ADDR, 0, 
RT_DIR_SOLID, (void *)&internal.idb_type, GED_ERROR);
+       GED_DB_PUT_INTERNAL(gedp, dp, &internal, &rt_uniresource, GED_ERROR);
+
+       bu_vls_printf(gedp->ged_result_str, "Generated pnts object %s\n", 
output_pnts_obj);
+    }
+
+pnts_internal_memfree:
+    rt_clean_resource(rtip, resp);
+    rt_free_rti(rtip);
+    rt_db_free_internal(&tpnts_intern);
+    BU_PUT(resp, struct resource);
+    BU_PUT(ap, struct appliation);
+
+    return pntcnt;
+}
+
+
+// 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


Property changes on: 
brlcad/branches/analyze_cmd/src/libged/analyze/op_pnts_vol.cpp
___________________________________________________________________
Added: svn:eol-style
## -0,0 +1 ##
+native
\ No newline at end of property
Added: svn:mime-type
## -0,0 +1 ##
+text/plain
\ No newline at end of property
Modified: brlcad/branches/analyze_cmd/src/libged/pnts_util.c
===================================================================
--- brlcad/branches/analyze_cmd/src/libged/pnts_util.c  2020-08-19 17:50:31 UTC 
(rev 76851)
+++ brlcad/branches/analyze_cmd/src/libged/pnts_util.c  2020-08-19 22:55:01 UTC 
(rev 76852)
@@ -392,6 +392,91 @@
     }
 }
 
+void *
+_ged_pnts_dup(void *point, rt_pnt_type type)
+{
+    void *npnt = NULL;
+    struct pnt *pstd, *pstdnew = NULL;
+    struct pnt_color *pc, *pcnew = NULL;
+    struct pnt_scale *ps, *psnew = NULL;
+    struct pnt_normal *pn, *pnnew = NULL;
+    struct pnt_color_scale *pcs, *pcsnew = NULL;
+    struct pnt_color_normal *pcn, *pcnnew = NULL;
+    struct pnt_scale_normal *psn, *psnnew = NULL;
+    struct pnt_color_scale_normal *pcsn, *pcsnnew = NULL;
+
+    switch (type) {
+       case RT_PNT_TYPE_PNT:
+           pstd = (struct pnt *)point;
+           npnt = _ged_pnts_new_pnt(type);
+           pstdnew = (struct pnt *)npnt;
+           VMOVE(pstdnew->v, pstd->v);
+           break;
+       case RT_PNT_TYPE_COL:
+           pc = (struct pnt_color *)point;
+           npnt = _ged_pnts_new_pnt(type);
+           pcnew = (struct pnt_color *)npnt;
+           VMOVE(pcnew->v, pc->v);
+           pcnew->c.buc_rgb[0] = pc->c.buc_rgb[0];
+           pcnew->c.buc_rgb[1] = pc->c.buc_rgb[1];
+           pcnew->c.buc_rgb[2] = pc->c.buc_rgb[2];
+           break;
+       case RT_PNT_TYPE_SCA:
+           ps = (struct pnt_scale *)point;
+           npnt = _ged_pnts_new_pnt(type);
+           psnew = (struct pnt_scale *)npnt;
+           VMOVE(psnew->v, ps->v);
+           psnew->s = ps->s;
+           break;
+       case RT_PNT_TYPE_NRM:
+           pn = (struct pnt_normal *)point;
+           npnt = _ged_pnts_new_pnt(type);
+           pnnew = (struct pnt_normal *)npnt;
+           VMOVE(pnnew->v, pn->v);
+           VMOVE(pnnew->n, pn->n);
+           break;
+       case RT_PNT_TYPE_COL_SCA:
+           pcs = (struct pnt_color_scale *)point;
+           npnt = _ged_pnts_new_pnt(type);
+           pcsnew = (struct pnt_color_scale *)npnt;
+           VMOVE(pcsnew->v, pcs->v);
+           pcsnew->c.buc_rgb[0] = pcs->c.buc_rgb[0];
+           pcsnew->c.buc_rgb[1] = pcs->c.buc_rgb[1];
+           pcsnew->c.buc_rgb[2] = pcs->c.buc_rgb[2];
+           pcsnew->s = pcs->s;
+           break;
+       case RT_PNT_TYPE_COL_NRM:
+           pcn = (struct pnt_color_normal *)point;
+           npnt = _ged_pnts_new_pnt(type);
+           pcnnew = (struct pnt_color_normal *)npnt;
+           VMOVE(pcnnew->v, pcn->v);
+           VMOVE(pcnnew->n, pcn->n);
+           break;
+       case RT_PNT_TYPE_SCA_NRM:
+           psn = (struct pnt_scale_normal *)point;
+           npnt = _ged_pnts_new_pnt(type);
+           psnnew = (struct pnt_scale_normal *)npnt;
+           VMOVE(psnnew->v, psn->v);
+           psnnew->s = psn->s;
+           VMOVE(psnnew->n, psn->n);
+           break;
+       case RT_PNT_TYPE_COL_SCA_NRM:
+           pcsn = (struct pnt_color_scale_normal *)point;
+           npnt = _ged_pnts_new_pnt(type);
+           pcsnnew = (struct pnt_color_scale_normal *)npnt;
+           VMOVE(pcsnnew->v, pcsn->v);
+           pcsnnew->c.buc_rgb[0] = pcsn->c.buc_rgb[0];
+           pcsnnew->c.buc_rgb[1] = pcsn->c.buc_rgb[1];
+           pcsnnew->c.buc_rgb[2] = pcsn->c.buc_rgb[2];
+           pcsnnew->s = pcsn->s;
+           VMOVE(pcsnnew->n, pcsn->n);
+           break;
+       default:
+           break;
+    }
+    return npnt;
+}
+
 /*
  * Local Variables:
  * tab-width: 8

Modified: brlcad/branches/analyze_cmd/src/libged/pnts_util.h
===================================================================
--- brlcad/branches/analyze_cmd/src/libged/pnts_util.h  2020-08-19 17:50:31 UTC 
(rev 76851)
+++ brlcad/branches/analyze_cmd/src/libged/pnts_util.h  2020-08-19 22:55:01 UTC 
(rev 76852)
@@ -60,6 +60,8 @@
 
 GED_EXPORT extern void _ged_pnts_add(struct rt_pnts_internal *pnts, void 
*point);
 
+GED_EXPORT extern void * _ged_pnts_dup(void *point, rt_pnt_type t);
+
 __END_DECLS
 
 #endif //LIBGED_PNT_GED_PRIVATE_H

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