Revision: 75663
http://sourceforge.net/p/brlcad/code/75663
Author: starseeker
Date: 2020-05-01 21:39:07 +0000 (Fri, 01 May 2020)
Log Message:
-----------
Start roughing out a rework of the bot command to make it similar to the new
form of the brep command. Still needs a fair bit of testing - in particular
the visualization for the bot checking code hasn't been tried, and the openvdb
based rework needs to be enabled/tested after moving. Goal is to bring
organization to the bot subcommands and make it cleaner to add new
functionality. Not going to move any of the bot_* commands until the initial
setup is complete and tested - right now just sticking to the commands that
were already in bot.c
Modified Paths:
--------------
brlcad/trunk/src/libged/CMakeLists.txt
Added Paths:
-----------
brlcad/trunk/src/libged/bot/
brlcad/trunk/src/libged/bot/bot.cpp
brlcad/trunk/src/libged/bot/check.cpp
brlcad/trunk/src/libged/bot/ged_bot.h
brlcad/trunk/src/libged/bot/remesh.cpp
Removed Paths:
-------------
brlcad/trunk/src/libged/bot.c
brlcad/trunk/src/libged/bot_remesh.cpp
Modified: brlcad/trunk/src/libged/CMakeLists.txt
===================================================================
--- brlcad/trunk/src/libged/CMakeLists.txt 2020-05-01 17:33:34 UTC (rev
75662)
+++ brlcad/trunk/src/libged/CMakeLists.txt 2020-05-01 21:39:07 UTC (rev
75663)
@@ -62,7 +62,9 @@
bigE.c
blast.c
bo.c
- bot.c
+ bot/bot.cpp
+ bot/check.cpp
+ bot/remesh.cpp
bot_condense.c
bot_decimate.c
bot_dump.c
@@ -71,7 +73,6 @@
bot_fuse.c
bot_flip.c
bot_merge.c
- bot_remesh.cpp
bot_smooth.c
bot_split.c
bot_sync.c
Added: brlcad/trunk/src/libged/bot/bot.cpp
===================================================================
--- brlcad/trunk/src/libged/bot/bot.cpp (rev 0)
+++ brlcad/trunk/src/libged/bot/bot.cpp 2020-05-01 21:39:07 UTC (rev 75663)
@@ -0,0 +1,387 @@
+/* B O T . 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 libged/bot/bot.cpp
+ *
+ * The LIBGED bot command.
+ *
+ */
+
+#include "common.h"
+
+#include <stdlib.h>
+#include <string.h>
+
+#include <algorithm>
+#include <fstream>
+#include <iomanip>
+#include <iostream>
+#include <list>
+#include <map>
+#include <queue>
+#include <set>
+#include <sstream>
+#include <string>
+#include <vector>
+
+#include "bu/cmd.h"
+#include "bu/color.h"
+#include "bu/opt.h"
+#include "bg/chull.h"
+#include "bg/trimesh.h"
+#include "rt/geom.h"
+#include "wdb.h"
+
+#include "./ged_bot.h"
+
+int
+_bot_cmd_msgs(void *bs, int argc, const char **argv, const char *us, const
char *ps)
+{
+ struct _ged_bot_info *gb = (struct _ged_bot_info *)bs;
+ if (argc == 2 && BU_STR_EQUAL(argv[1], HELPFLAG)) {
+ bu_vls_printf(gb->gedp->ged_result_str, "%s\n%s\n", us, ps);
+ return 1;
+ }
+ if (argc == 2 && BU_STR_EQUAL(argv[1], PURPOSEFLAG)) {
+ bu_vls_printf(gb->gedp->ged_result_str, "%s\n", ps);
+ return 1;
+ }
+ return 0;
+}
+
+extern "C" int
+_bot_cmd_get(void *bs, int argc, const char **argv)
+{
+ const char *usage_string = "bot [options] <objname> get
<faces|minEdge|maxEdge|orientation|type|vertices>";
+ const char *purpose_string = "Report specific information about a BoT
shape";
+ if (_bot_cmd_msgs(bs, argc, argv, usage_string, purpose_string)) {
+ return GED_OK;
+ }
+
+ struct _ged_bot_info *gb = (struct _ged_bot_info *)bs;
+
+ if (gb->intern.idb_minor_type != DB5_MINORTYPE_BRLCAD_BOT) {
+ bu_vls_printf(gb->gedp->ged_result_str, ": object %s is not of type
bot\n", gb->solid_name.c_str());
+ return GED_ERROR;
+ }
+
+ return GED_OK;
+}
+
+extern "C" int
+_bot_cmd_chull(void *bs, int argc, const char **argv)
+{
+ const char *usage_string = "bot [options] <objname> chull output_bot";
+ const char *purpose_string = "Generate the BoT's convex hull and store it
in object <output_bot>";
+ if (_bot_cmd_msgs(bs, argc, argv, usage_string, purpose_string)) {
+ return GED_OK;
+ }
+
+ struct _ged_bot_info *gb = (struct _ged_bot_info *)bs;
+
+ if (gb->intern.idb_minor_type != DB5_MINORTYPE_BRLCAD_BOT) {
+ bu_vls_printf(gb->gedp->ged_result_str, ": object %s is not of type
bot\n", gb->solid_name.c_str());
+ return GED_ERROR;
+ }
+
+ struct rt_bot_internal *bot = (struct rt_bot_internal
*)(gb->intern.idb_ptr);
+ int retval = 0;
+ int fc = 0;
+ int vc = 0;
+ point_t *vert_array;
+ int *faces;
+ unsigned char err = 0;
+
+ /* must be wanting help */
+ if (argc < 2) {
+ bu_vls_printf(gb->gedp->ged_result_str, "%s\n%s\n", usage_string,
purpose_string);
+ return GED_ERROR;
+ }
+
+ retval = bg_3d_chull(&faces, &fc, &vert_array, &vc, (const point_t
*)bot->vertices, (int)bot->num_vertices);
+
+ if (retval != 3) {
+ return GED_ERROR;
+ }
+
+ retval = mk_bot(gb->gedp->ged_wdbp, argv[1], RT_BOT_SOLID, RT_BOT_CCW,
err, vc, fc, (fastf_t *)vert_array, faces, NULL, NULL);
+
+ bu_free(faces, "free faces");
+ bu_free(vert_array, "free verts");
+
+ if (retval) {
+ return GED_ERROR;
+ }
+
+ return GED_OK;
+}
+
+extern "C" int
+_bot_cmd_isect(void *bs, int argc, const char **argv)
+{
+ const char *usage_string = "bot [options] <objname> isect <objname2>";
+ const char *purpose_string = "(TODO) Test if BoT <objname> intersects with
BoT <objname2>";
+ if (_bot_cmd_msgs(bs, argc, argv, usage_string, purpose_string)) {
+ return GED_OK;
+ }
+
+ struct _ged_bot_info *gb = (struct _ged_bot_info *)bs;
+
+ if (gb->intern.idb_minor_type != DB5_MINORTYPE_BRLCAD_BOT) {
+ bu_vls_printf(gb->gedp->ged_result_str, ": object %s is not of type
bot\n", gb->solid_name.c_str());
+ return GED_ERROR;
+ }
+
+
+ if (argc != 2) {
+ bu_vls_printf(gb->gedp->ged_result_str, "%s", usage_string);
+ return GED_ERROR;
+ }
+
+ struct rt_bot_internal *bot = (struct rt_bot_internal *)gb->intern.idb_ptr;
+ struct directory *bot_dp_2;
+ struct rt_db_internal intern_2;
+ struct rt_bot_internal *bot_2;
+
+ GED_DB_LOOKUP(gb->gedp, bot_dp_2, argv[2], LOOKUP_NOISY, GED_ERROR &
GED_QUIET);
+ GED_DB_GET_INTERNAL(gb->gedp, &intern_2, bot_dp_2, bn_mat_identity,
&rt_uniresource, GED_ERROR);
+
+ if (intern_2.idb_major_type != DB5_MAJORTYPE_BRLCAD ||
intern_2.idb_minor_type != DB5_MINORTYPE_BRLCAD_BOT) {
+ bu_vls_printf(gb->gedp->ged_result_str, ": object %s is not of type
bot\n", argv[2]);
+ rt_db_free_internal(&intern_2);
+ return GED_ERROR;
+ }
+ bot_2 = (struct rt_bot_internal *)intern_2.idb_ptr;
+
+ int fc_1 = (int)bot->num_faces;
+ int fc_2 = (int)bot_2->num_faces;
+ int vc_1 = (int)bot->num_vertices;
+ int vc_2 = (int)bot_2->num_vertices;
+ point_t *verts_1 = (point_t *)bot->vertices;
+ point_t *verts_2 = (point_t *)bot_2->vertices;
+ int *faces_1 = bot->faces;
+ int *faces_2 = bot_2->faces;
+
+ (void)bg_trimesh_isect(NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL,
+ faces_1, fc_1, verts_1, vc_1, faces_2, fc_2, verts_2, vc_2);
+
+ rt_db_free_internal(&intern_2);
+
+ return GED_OK;
+}
+
+
+extern "C" int
+_bot_cmd_help(void *bs, int argc, const char **argv)
+{
+ struct _ged_bot_info *gb = (struct _ged_bot_info *)bs;
+ if (!argc || !argv || BU_STR_EQUAL(argv[0], "help")) {
+ bu_vls_printf(gb->gedp->ged_result_str, "bot [options] <objname>
subcommand [args]\n");
+ if (gb->gopts) {
+ char *option_help = bu_opt_describe(gb->gopts, NULL);
+ if (option_help) {
+ bu_vls_printf(gb->gedp->ged_result_str, "Options:\n%s\n",
option_help);
+ bu_free(option_help, "help str");
+ }
+ }
+ bu_vls_printf(gb->gedp->ged_result_str, "Available subcommands:\n");
+ const struct bu_cmdtab *ctp = NULL;
+ int ret;
+ const char *helpflag[2];
+ helpflag[1] = PURPOSEFLAG;
+ size_t maxcmdlen = 0;
+ for (ctp = gb->cmds; ctp->ct_name != (char *)NULL; ctp++) {
+ maxcmdlen = (maxcmdlen > strlen(ctp->ct_name)) ? maxcmdlen :
strlen(ctp->ct_name);
+ }
+ for (ctp = gb->cmds; ctp->ct_name != (char *)NULL; ctp++) {
+ bu_vls_printf(gb->gedp->ged_result_str, " %s%*s", ctp->ct_name,
(int)(maxcmdlen - strlen(ctp->ct_name)) + 2, " ");
+ if (!BU_STR_EQUAL(ctp->ct_name, "help")) {
+ helpflag[0] = ctp->ct_name;
+ bu_cmd(gb->cmds, 2, helpflag, 0, (void *)gb, &ret);
+ } else {
+ bu_vls_printf(gb->gedp->ged_result_str, "print help and
exit\n");
+ }
+ }
+ } else {
+ int ret;
+ const char **helpargv = (const char **)bu_calloc(argc+1, sizeof(char
*), "help argv");
+ helpargv[0] = argv[0];
+ helpargv[1] = HELPFLAG;
+ for (int i = 1; i < argc; i++) {
+ helpargv[i+1] = argv[i];
+ }
+ bu_cmd(gb->cmds, argc+1, helpargv, 0, (void *)gb, &ret);
+ bu_free(helpargv, "help argv");
+ return ret;
+ }
+
+ return GED_OK;
+}
+
+const struct bu_cmdtab _bot_cmds[] = {
+ { "get", _bot_cmd_get},
+ { "check", _bot_cmd_check},
+ { "chull", _bot_cmd_chull},
+ { "isect", _bot_cmd_isect},
+ { "remesh", _bot_cmd_remesh},
+ { (char *)NULL, NULL}
+};
+
+
+static int
+_ged_bot_opt_color(struct bu_vls *msg, size_t argc, const char **argv, void
*set_c)
+{
+ struct bu_color **set_color = (struct bu_color **)set_c;
+ BU_GET(*set_color, struct bu_color);
+ return bu_opt_color(msg, argc, argv, (void *)(*set_color));
+}
+
+extern "C" int
+ged_bot(struct ged *gedp, int argc, const char *argv[])
+{
+ int help = 0;
+ struct _ged_bot_info gb;
+ gb.gedp = gedp;
+ gb.cmds = _bot_cmds;
+ gb.verbosity = 0;
+ struct bu_color *color = NULL;
+
+ // Sanity
+ if (UNLIKELY(!gedp || !argc || !argv)) {
+ return GED_ERROR;
+ }
+
+ // Clear results
+ bu_vls_trunc(gedp->ged_result_str, 0);
+
+ // We know we're the bot command - start processing args
+ argc--; argv++;
+
+ // See if we have any high level options set
+ struct bu_opt_desc d[5];
+ BU_OPT(d[0], "h", "help", "", NULL, &help,
"Print help");
+ BU_OPT(d[1], "v", "verbose", "", NULL, &gb.verbosity,
"Verbose output");
+ BU_OPT(d[2], "V", "visualize", "", NULL, &gb.visualize,
"Visualize results");
+ BU_OPT(d[3], "C", "color", "r/g/b", &_ged_bot_opt_color, &color,
"Set plotting color");
+ BU_OPT_NULL(d[4]);
+
+ gb.gopts = d;
+
+ if (!argc) {
+ _bot_cmd_help(&gb, 0, NULL);
+ return GED_OK;
+ }
+
+ // High level options are only defined prior to the subcommand
+ int cmd_pos = -1;
+ for (int i = 0; i < argc; i++) {
+ if (bu_cmd_valid(_bot_cmds, argv[i]) == BRLCAD_OK) {
+ cmd_pos = i;
+ break;
+ }
+ }
+
+ int acnt = (cmd_pos >= 0) ? cmd_pos : argc;
+
+ int opt_ret = bu_opt_parse(NULL, acnt, argv, d);
+
+ if (help) {
+ if (cmd_pos >= 0) {
+ argc = argc - cmd_pos;
+ argv = &argv[cmd_pos];
+ _bot_cmd_help(&gb, argc, argv);
+ } else {
+ _bot_cmd_help(&gb, 0, NULL);
+ }
+ return GED_OK;
+ }
+
+ // Must have a subcommand
+ if (cmd_pos == -1) {
+ bu_vls_printf(gedp->ged_result_str, ": no valid subcommand
specified\n");
+ _bot_cmd_help(&gb, 0, NULL);
+ return GED_ERROR;
+ }
+
+
+ if (opt_ret != 1) {
+ bu_vls_printf(gedp->ged_result_str, ": no object specified before
subcommand\n");
+ bu_vls_printf(gedp->ged_result_str, "bot [options] <objname> subcommand
[args]\n");
+ if (color) {
+ BU_PUT(color, struct bu_color);
+ }
+ return GED_ERROR;
+ }
+
+ GED_CHECK_DATABASE_OPEN(gedp, GED_ERROR);
+ GED_CHECK_DRAWABLE(gedp, GED_ERROR);
+ GED_CHECK_ARGC_GT_0(gedp, argc, GED_ERROR);
+
+ gb.solid_name = std::string(argv[0]);
+ gb.dp = db_lookup(gedp->ged_wdbp->dbip, gb.solid_name.c_str(),
LOOKUP_NOISY);
+ if (gb.dp == RT_DIR_NULL) {
+ bu_vls_printf(gedp->ged_result_str, ": %s is not a solid or does not
exist in database", gb.solid_name.c_str());
+ if (color) {
+ BU_PUT(color, struct bu_color);
+ }
+ return GED_ERROR;
+ } else {
+ int real_flag = (gb.dp->d_addr == RT_DIR_PHONY_ADDR) ? 0 : 1;
+ if (!real_flag) {
+ /* solid doesn't exist */
+ bu_vls_printf(gedp->ged_result_str, ": %s is not a real solid",
gb.solid_name.c_str());
+ if (color) {
+ BU_PUT(color, struct bu_color);
+ }
+ return GED_ERROR;
+ }
+ }
+
+ GED_DB_GET_INTERNAL(gedp, &gb.intern, gb.dp, bn_mat_identity,
&rt_uniresource, GED_ERROR);
+ RT_CK_DB_INTERNAL(&gb.intern);
+
+ gb.vbp = rt_vlblock_init();
+ gb.color = color;
+
+ // Jump the processing past any options specified
+ argc = argc - cmd_pos;
+ argv = &argv[cmd_pos];
+
+ int ret;
+ if (bu_cmd(_bot_cmds, argc, argv, 0, (void *)&gb, &ret) == BRLCAD_OK) {
+ rt_db_free_internal(&gb.intern);
+ return ret;
+ } else {
+ bu_vls_printf(gedp->ged_result_str, "subcommand %s not defined",
argv[0]);
+ }
+
+ bn_vlblock_free(gb.vbp);
+ gb.vbp = (struct bn_vlblock *)NULL;
+ rt_db_free_internal(&gb.intern);
+ return GED_ERROR;
+}
+
+// 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/trunk/src/libged/bot/bot.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
Added: brlcad/trunk/src/libged/bot/check.cpp
===================================================================
--- brlcad/trunk/src/libged/bot/check.cpp (rev 0)
+++ brlcad/trunk/src/libged/bot/check.cpp 2020-05-01 21:39:07 UTC (rev
75663)
@@ -0,0 +1,745 @@
+#include "common.h"
+
+#include <stdlib.h>
+#include <ctype.h>
+#include <string.h>
+
+#include "bu/cmd.h"
+#include "bu/opt.h"
+#include "bu/sort.h"
+#include "bg/chull.h"
+#include "bg/trimesh.h"
+#include "rt/geom.h"
+#include "wdb.h"
+#include "./ged_bot.h"
+
+
+struct _ged_bot_icheck {
+ struct _ged_bot_info *gb;
+ struct bu_vls *vls;
+ const struct bu_cmdtab *cmds;
+};
+
+/* for bsearch() */
+static int
+edge_compare(const void *a, const void *b)
+{
+ const int *edge_a = (int *)a;
+ const int *edge_b = (int *)b;
+ int diff = edge_a[0] - edge_b[0];
+ return diff ? diff : edge_a[1] - edge_b[1];
+}
+
+/* for bu_sort() */
+static int
+edge_cmp(const void *a, const void *b, void *UNUSED(context))
+{
+ return edge_compare(a, b);
+}
+
+static int
+is_edge_in_list(int edge[2], struct bg_trimesh_edges list)
+{
+ return (bsearch(edge, list.edges, list.count, sizeof(int) * 2,
edge_compare) != NULL);
+}
+
+static int
+is_edge_in_lists(int edge[2], struct bg_trimesh_edges lists[], int num_lists)
+{
+ int i;
+ for (i = 0; i < num_lists; ++i) {
+ if (is_edge_in_list(edge, lists[i])) {
+ return 1;
+ }
+ }
+ return 0;
+}
+
+static struct bg_trimesh_edges*
+make_edges(int edge_count)
+{
+ struct bg_trimesh_edges *edges;
+ BU_ALLOC(edges, struct bg_trimesh_edges);
+ edges->count = 0;
+ edges->edges = (int *)bu_malloc(edge_count * 2 * sizeof(int), "make
edges");
+ return edges;
+}
+
+static void
+copy_edge(int dst[2], int src[2])
+{
+ dst[0] = src[0];
+ dst[1] = src[1];
+}
+
+static void
+append_edge(struct bg_trimesh_edges *list, int edge[2])
+{
+ copy_edge(&list->edges[list->count * 2], edge);
+ ++(list->count);
+}
+
+static void
+append_edge_if_not_in_lists(struct bg_trimesh_edges *dst, int edge[2], struct
bg_trimesh_edges lists[], int num_lists)
+{
+ if (!is_edge_in_lists(edge, lists, num_lists)) {
+ append_edge(dst, edge);
+ }
+}
+
+static struct bg_trimesh_edges*
+edges_not_in_lists(struct bg_trimesh_edges all, struct bg_trimesh_edges
lists[], int num_lists)
+{
+ int i;
+ struct bg_trimesh_edges *remaining = make_edges(all.count);
+
+ for (i = 0; i < all.count; ++i) {
+ append_edge_if_not_in_lists(remaining, &all.edges[i * 2], lists,
num_lists);
+ }
+ return remaining;
+}
+
+static struct bg_trimesh_edges*
+edges_from_half_edges(struct bg_trimesh_halfedge edge_list[], int num_edges)
+{
+ int i;
+ struct bg_trimesh_edges *edges = make_edges(num_edges);
+
+ for (i = 0; i < num_edges; ++i) {
+ int half_edge[2];
+ half_edge[0] = edge_list[i].va;
+ half_edge[1] = edge_list[i].vb;
+ append_edge_if_not_in_lists(edges, half_edge, edges, 1);
+ }
+ return edges;
+}
+
+static void
+standardize_edge(int edge[2])
+{
+ if (edge[1] < edge[0]) {
+ int tmp = edge[0];
+ edge[0] = edge[1];
+ edge[1] = tmp;
+ }
+}
+
+static void
+append_face_edges(struct bg_trimesh_edges *edges, int face[3])
+{
+ int i, edge[2];
+ for (i = 0; i < 3; ++i) {
+ edge[0] = face[i];
+ edge[1] = face[(i + 1) % 3];
+ standardize_edge(edge);
+ append_edge(edges, edge);
+ }
+}
+
+static struct bg_trimesh_edges*
+non_unique_face_edges(struct bg_trimesh_faces faces, struct rt_bot_internal
*bot)
+{
+ int i;
+ struct bg_trimesh_edges *edges = make_edges(faces.count * 3);
+
+ for (i = 0; i < faces.count; ++i) {
+ append_face_edges(edges, &bot->faces[faces.faces[i] * 3]);
+ }
+ bu_sort(edges->edges, edges->count, sizeof(int) * 2, edge_cmp, NULL);
+ return edges;
+}
+
+static struct bg_trimesh_edges*
+face_edges(struct bg_trimesh_faces faces, struct rt_bot_internal *bot)
+{
+ int i;
+ struct bg_trimesh_edges *unique_edges = make_edges(faces.count * 3);
+ struct bg_trimesh_edges *all_edges = non_unique_face_edges(faces, bot);
+
+ for (i = 0; i < all_edges->count; ++i) {
+ append_edge_if_not_in_lists(unique_edges, &all_edges->edges[i * 2],
unique_edges, 1);
+ }
+ bg_free_trimesh_edges(all_edges);
+ BU_FREE(all_edges, struct bg_trimesh_edges);
+
+ return unique_edges;
+}
+
+static struct bg_trimesh_faces*
+make_faces(int num_faces)
+{
+ struct bg_trimesh_faces *faces;
+ BU_ALLOC(faces, struct bg_trimesh_faces);
+
+ faces->count = 0;
+ faces->faces = (int *)bu_malloc(sizeof(int) * num_faces, "make faces");
+ return faces;
+}
+
+static struct bg_trimesh_faces*
+faces_from_bot(struct rt_bot_internal *bot)
+{
+ int i;
+ struct bg_trimesh_faces *faces = make_faces((int)bot->num_faces);
+ faces->count = (int)bot->num_faces;
+ for (i = 0; i < faces->count; ++i) {
+ faces->faces[i] = i;
+ }
+ return faces;
+}
+
+static struct bg_trimesh_edges*
+edges_from_bot(struct rt_bot_internal *bot)
+{
+ struct bg_trimesh_faces *faces = faces_from_bot(bot);
+ struct bg_trimesh_edges *edges = face_edges(*faces, bot);
+
+ bg_free_trimesh_faces(faces);
+ BU_FREE(faces, struct bg_trimesh_faces);
+
+ return edges;
+}
+
+static void
+draw_edges(struct bn_vlblock *vbp, struct rt_bot_internal *bot, int num_edges,
int edges[], struct bu_color *color)
+{
+ struct bu_list *vhead;
+ point_t a,b;
+ unsigned char draw_color[3];
+ bu_color_to_rgb_chars(color, draw_color);
+
+ for (int curr_edge = 0; curr_edge < num_edges; curr_edge++) {
+ int p1 = edges[curr_edge*2];
+ int p2 = edges[curr_edge*2+1];
+ VSET(a, bot->vertices[p1*3], bot->vertices[p1*3+1],
bot->vertices[p1*3+2]);
+ VSET(b, bot->vertices[p2*3], bot->vertices[p2*3+1],
bot->vertices[p2*3+2]);
+ vhead = bn_vlblock_find(vbp, draw_color[0], draw_color[1],
draw_color[2]);
+ BN_ADD_VLIST(vbp->free_vlist_hd, vhead, a, BN_VLIST_LINE_MOVE);
+ BN_ADD_VLIST(vbp->free_vlist_hd, vhead, b, BN_VLIST_LINE_DRAW);
+ }
+}
+
+
+static int
+_bot_check_msgs(void *bs, int argc, const char **argv, const char *us, const
char *ps)
+{
+ struct _ged_bot_icheck *gb = (struct _ged_bot_icheck *)bs;
+ if (argc == 2 && BU_STR_EQUAL(argv[1], HELPFLAG)) {
+ bu_vls_printf(gb->vls, "%s\n%s\n", us, ps);
+ return 1;
+ }
+ if (argc == 2 && BU_STR_EQUAL(argv[1], PURPOSEFLAG)) {
+ bu_vls_printf(gb->vls, "%s\n", ps);
+ return 1;
+ }
+ return 0;
+}
+
+
+extern "C" int
+_bot_cmd_degen_faces(void *bs, int argc, const char **argv)
+{
+ const char *usage_string = "bot [options] <objname1> degen_faces";
+ const char *purpose_string = "Check BoT for degenerate faces";
+ if (_bot_check_msgs(bs, argc, argv, usage_string, purpose_string)) {
+ return GED_OK;
+ }
+
+ argc--;argv++;
+
+ struct _ged_bot_icheck *gib = (struct _ged_bot_icheck *)bs;
+
+ if (gib->gb->intern.idb_minor_type != DB5_MINORTYPE_BRLCAD_BOT) {
+ bu_vls_printf(gib->gb->gedp->ged_result_str, ": object %s is not of
type bot\n", gib->gb->solid_name.c_str());
+ return GED_ERROR;
+ }
+
+ struct rt_bot_internal *bot = (struct rt_bot_internal
*)(gib->gb->intern.idb_ptr);
+ struct bu_color *color = gib->gb->color;
+ struct bn_vlblock *vbp = gib->gb->vbp;
+
+ struct bg_trimesh_faces degenerate = BG_TRIMESH_FACES_INIT_NULL;
+ struct bg_trimesh_edges *degen_edges, *all_edges, *other_edges;
+ int degenerate_faces = 0;
+ int num_faces = (int)bot->num_faces;
+
+ if (gib->gb->visualize) {
+ /* first pass - count errors */
+ degenerate_faces = bg_trimesh_degenerate_faces(num_faces, bot->faces,
bg_trimesh_face_continue, NULL);
+
+ if (degenerate_faces) {
+ /* second pass - generate error faces array and draw it */
+ degenerate.count = 0;
+ degenerate.faces = (int *)bu_calloc(degenerate_faces, sizeof(int),
"degenerate faces");
+ bg_trimesh_degenerate_faces(num_faces, bot->faces,
bg_trimesh_face_gather, °enerate);
+
+ degen_edges = face_edges(degenerate, bot);
+ bg_free_trimesh_faces(°enerate);
+
+ all_edges = edges_from_bot(bot);
+ other_edges = edges_not_in_lists(*all_edges, degen_edges, 1);
+ bg_free_trimesh_edges(all_edges);
+ BU_FREE(all_edges, struct bg_trimesh_edges);
+
+ draw_edges(vbp, bot, degen_edges->count, degen_edges->edges, color);
+ struct bu_color red = BU_COLOR_INIT_ZERO;
+ bu_color_from_str(&red, "255/0/0");
+ draw_edges(vbp, bot, other_edges->count, other_edges->edges, &red);
+
+ bg_free_trimesh_edges(degen_edges);
+ BU_FREE(degen_edges, struct bg_trimesh_edges);
+ bg_free_trimesh_edges(other_edges);
+ BU_FREE(other_edges, struct bg_trimesh_edges);
+ }
+ } else {
+ /* fast path - exit on first error */
+ degenerate_faces = bg_trimesh_degenerate_faces(num_faces, bot->faces,
bg_trimesh_face_exit, NULL);
+ }
+
+ bu_vls_printf(gib->vls, degenerate_faces ? "1" : "0");
+
+ if (gib->gb->visualize) {
+ struct bu_vls sname = BU_VLS_INIT_ZERO;
+ bu_vls_sprintf(&sname, "_%s_degen_faces", gib->gb->solid_name.c_str());
+ if (db_lookup(gib->gb->gedp->ged_wdbp->dbip, bu_vls_cstr(&sname),
LOOKUP_QUIET) != RT_DIR_NULL) {
+ dl_erasePathFromDisplay(gib->gb->gedp->ged_gdp->gd_headDisplay,
gib->gb->gedp->ged_wdbp->dbip, gib->gb->gedp->ged_free_vlist_callback,
bu_vls_cstr(&sname), 1, gib->gb->gedp->freesolid);
+ }
+ _ged_cvt_vlblock_to_solids(gib->gb->gedp, vbp, bu_vls_cstr(&sname), 0);
+ bu_vls_free(&sname);
+ }
+
+ return GED_OK;
+}
+
+extern "C" int
+_bot_cmd_extra_edges(void *bs, int argc, const char **argv)
+{
+ const char *usage_string = "bot [options] <objname1> extra_edges";
+ const char *purpose_string = "Check BoT for edges which are not part of
any triangle faces";
+ if (_bot_check_msgs(bs, argc, argv, usage_string, purpose_string)) {
+ return GED_OK;
+ }
+
+ argc--;argv++;
+
+ struct _ged_bot_icheck *gib = (struct _ged_bot_icheck *)bs;
+
+ if (gib->gb->intern.idb_minor_type != DB5_MINORTYPE_BRLCAD_BOT) {
+ bu_vls_printf(gib->gb->gedp->ged_result_str, ": object %s is not of
type bot\n", gib->gb->solid_name.c_str());
+ return GED_ERROR;
+ }
+
+ struct rt_bot_internal *bot = (struct rt_bot_internal
*)(gib->gb->intern.idb_ptr);
+ struct bu_color *color = gib->gb->color;
+ struct bn_vlblock *vbp = gib->gb->vbp;
+
+
+ int num_faces, num_edges;
+ num_faces = (int)bot->num_faces;
+ num_edges = num_faces * 3;
+
+ /* generate half-edge list */
+ struct bg_trimesh_halfedge *edge_list;
+ if (!(edge_list = bg_trimesh_generate_edge_list(num_faces, bot->faces))) {
+ bu_vls_printf(gib->vls, "ERROR: failed to generate an edge list\n");
+ return GED_ERROR;
+ }
+
+ int extra_edges = 0;
+
+ if (gib->gb->visualize) {
+ /* first pass - count errors */
+ struct bg_trimesh_edges error_edges = BG_TRIMESH_EDGES_INIT_NULL;
+ struct bg_trimesh_edges *all_edges, *other_edges;
+
+ extra_edges = bg_trimesh_excess_edges(num_edges, edge_list,
bg_trimesh_edge_continue, NULL);
+
+ if (extra_edges) {
+ /* second pass - generate error edge array and draw it */
+ error_edges.count = 0;
+ error_edges.edges = (int *)bu_calloc(extra_edges * 2, sizeof(int),
"error edges");
+ extra_edges = bg_trimesh_excess_edges(num_edges, edge_list,
bg_trimesh_edge_gather, &error_edges);
+
+ all_edges = edges_from_half_edges(edge_list, num_edges);
+ other_edges = edges_not_in_lists(*all_edges, &error_edges, 1);
+ bg_free_trimesh_edges(all_edges);
+ BU_FREE(all_edges, struct bg_trimesh_edges);
+
+ draw_edges(vbp, bot, error_edges.count, error_edges.edges, color);
+ struct bu_color red = BU_COLOR_INIT_ZERO;
+ bu_color_from_str(&red, "255/0/0");
+ draw_edges(vbp, bot, other_edges->count, other_edges->edges, &red);
+
+ bg_free_trimesh_edges(&error_edges);
+ bg_free_trimesh_edges(other_edges);
+ BU_FREE(other_edges, struct bg_trimesh_edges);
+ }
+ } else {
+ /* fast path - exit on first error */
+ extra_edges = bg_trimesh_excess_edges(num_edges, edge_list,
bg_trimesh_edge_exit, NULL);
+ }
+
+ bu_free(edge_list, "edge list");
+
+ bu_vls_printf(gib->vls, extra_edges ? "1" : "0");
+
+ if (gib->gb->visualize) {
+ struct bu_vls sname = BU_VLS_INIT_ZERO;
+ bu_vls_sprintf(&sname, "_%s_extra_edges", gib->gb->solid_name.c_str());
+ if (db_lookup(gib->gb->gedp->ged_wdbp->dbip, bu_vls_cstr(&sname),
LOOKUP_QUIET) != RT_DIR_NULL) {
+ dl_erasePathFromDisplay(gib->gb->gedp->ged_gdp->gd_headDisplay,
gib->gb->gedp->ged_wdbp->dbip, gib->gb->gedp->ged_free_vlist_callback,
bu_vls_cstr(&sname), 1, gib->gb->gedp->freesolid);
+ }
+ _ged_cvt_vlblock_to_solids(gib->gb->gedp, vbp, bu_vls_cstr(&sname), 0);
+ bu_vls_free(&sname);
+ }
+
+ return GED_OK;
+}
+
+extern "C" int
+_bot_cmd_flipped_edges(void *bs, int argc, const char **argv)
+{
+ const char *usage_string = "bot [options] <objname1> flipped_edges";
+ const char *purpose_string = "Check BoT for edges which are incorrectly
oriented";
+ if (_bot_check_msgs(bs, argc, argv, usage_string, purpose_string)) {
+ return GED_OK;
+ }
+
+ argc--;argv++;
+
+ struct _ged_bot_icheck *gib = (struct _ged_bot_icheck *)bs;
+
+ if (gib->gb->intern.idb_minor_type != DB5_MINORTYPE_BRLCAD_BOT) {
+ bu_vls_printf(gib->gb->gedp->ged_result_str, ": object %s is not of
type bot\n", gib->gb->solid_name.c_str());
+ return GED_ERROR;
+ }
+
+ struct rt_bot_internal *bot = (struct rt_bot_internal
*)(gib->gb->intern.idb_ptr);
+ struct bu_color *color = gib->gb->color;
+ struct bn_vlblock *vbp = gib->gb->vbp;
+
+
+ int num_faces, num_edges;
+ num_faces = (int)bot->num_faces;
+ num_edges = num_faces * 3;
+
+ /* generate half-edge list */
+ struct bg_trimesh_halfedge *edge_list;
+ if (!(edge_list = bg_trimesh_generate_edge_list(num_faces, bot->faces))) {
+ bu_vls_printf(gib->vls, "ERROR: failed to generate an edge list\n");
+ return GED_ERROR;
+ }
+
+ int flipped_edges = 0;
+
+ if (gib->gb->visualize) {
+ /* first pass - count errors */
+ struct bg_trimesh_edges error_edges = BG_TRIMESH_EDGES_INIT_NULL;
+ struct bg_trimesh_edges *all_edges, *other_edges;
+
+ flipped_edges = bg_trimesh_misoriented_edges(num_edges, edge_list,
bg_trimesh_edge_continue, NULL);
+
+ if (flipped_edges) {
+ /* second pass - generate error edge array and draw it */
+ error_edges.count = 0;
+ error_edges.edges = (int *)bu_calloc(flipped_edges * 2,
sizeof(int), "error edges");
+ flipped_edges = bg_trimesh_misoriented_edges(num_edges, edge_list,
bg_trimesh_edge_gather, &error_edges);
+
+ all_edges = edges_from_half_edges(edge_list, num_edges);
+ other_edges = edges_not_in_lists(*all_edges, &error_edges, 1);
+ bg_free_trimesh_edges(all_edges);
+ BU_FREE(all_edges, struct bg_trimesh_edges);
+
+ draw_edges(vbp, bot, error_edges.count, error_edges.edges, color);
+ struct bu_color red = BU_COLOR_INIT_ZERO;
+ bu_color_from_str(&red, "255/0/0");
+ draw_edges(vbp, bot, other_edges->count, other_edges->edges, &red);
+
+ bg_free_trimesh_edges(&error_edges);
+ bg_free_trimesh_edges(other_edges);
+ BU_FREE(other_edges, struct bg_trimesh_edges);
+ }
+ } else {
+ /* fast path - exit on first error */
+ flipped_edges = bg_trimesh_excess_edges(num_edges, edge_list,
bg_trimesh_edge_exit, NULL);
+ }
+
+ bu_free(edge_list, "edge list");
+
+ bu_vls_printf(gib->vls, flipped_edges ? "1" : "0");
+
+ if (gib->gb->visualize) {
+ struct bu_vls sname = BU_VLS_INIT_ZERO;
+ bu_vls_sprintf(&sname, "_%s_flipped_edges",
gib->gb->solid_name.c_str());
+ if (db_lookup(gib->gb->gedp->ged_wdbp->dbip, bu_vls_cstr(&sname),
LOOKUP_QUIET) != RT_DIR_NULL) {
+ dl_erasePathFromDisplay(gib->gb->gedp->ged_gdp->gd_headDisplay,
gib->gb->gedp->ged_wdbp->dbip, gib->gb->gedp->ged_free_vlist_callback,
bu_vls_cstr(&sname), 1, gib->gb->gedp->freesolid);
+ }
+ _ged_cvt_vlblock_to_solids(gib->gb->gedp, vbp, bu_vls_cstr(&sname), 0);
+ bu_vls_free(&sname);
+ }
+
+ return GED_OK;
+}
+
+extern "C" int
+_bot_cmd_open_edges(void *bs, int argc, const char **argv)
+{
+ const char *usage_string = "bot [options] <objname1> open_edges";
+ const char *purpose_string = "Check BoT for edges which are not connected
to two triangle faces";
+ if (_bot_check_msgs(bs, argc, argv, usage_string, purpose_string)) {
+ return GED_OK;
+ }
+
+ argc--;argv++;
+
+ struct _ged_bot_icheck *gib = (struct _ged_bot_icheck *)bs;
+
+ if (gib->gb->intern.idb_minor_type != DB5_MINORTYPE_BRLCAD_BOT) {
+ bu_vls_printf(gib->gb->gedp->ged_result_str, ": object %s is not of
type bot\n", gib->gb->solid_name.c_str());
+ return GED_ERROR;
+ }
+
+ struct rt_bot_internal *bot = (struct rt_bot_internal
*)(gib->gb->intern.idb_ptr);
+ struct bu_color *color = gib->gb->color;
+ struct bn_vlblock *vbp = gib->gb->vbp;
+
+
+ int num_faces, num_edges;
+ num_faces = (int)bot->num_faces;
+ num_edges = num_faces * 3;
+
+ /* generate half-edge list */
+ struct bg_trimesh_halfedge *edge_list;
+ if (!(edge_list = bg_trimesh_generate_edge_list(num_faces, bot->faces))) {
+ bu_vls_printf(gib->vls, "ERROR: failed to generate an edge list\n");
+ return GED_ERROR;
+ }
+
+ int open_edges = 0;
+
+ if (gib->gb->visualize) {
+ /* first pass - count errors */
+ struct bg_trimesh_edges error_edges = BG_TRIMESH_EDGES_INIT_NULL;
+ struct bg_trimesh_edges *all_edges, *other_edges;
+
+ open_edges = bg_trimesh_unmatched_edges(num_edges, edge_list,
bg_trimesh_edge_continue, NULL);
+
+ if (open_edges) {
+ /* second pass - generate error edge array and draw it */
+ error_edges.count = 0;
+ error_edges.edges = (int *)bu_calloc(open_edges * 2, sizeof(int),
"error edges");
+ open_edges = bg_trimesh_unmatched_edges(num_edges, edge_list,
bg_trimesh_edge_gather, &error_edges);
+
+ all_edges = edges_from_half_edges(edge_list, num_edges);
+ other_edges = edges_not_in_lists(*all_edges, &error_edges, 1);
+ bg_free_trimesh_edges(all_edges);
+ BU_FREE(all_edges, struct bg_trimesh_edges);
+
+ draw_edges(vbp, bot, error_edges.count, error_edges.edges, color);
+ struct bu_color red = BU_COLOR_INIT_ZERO;
+ bu_color_from_str(&red, "255/0/0");
+ draw_edges(vbp, bot, other_edges->count, other_edges->edges, &red);
+
+ bg_free_trimesh_edges(&error_edges);
+ bg_free_trimesh_edges(other_edges);
+ BU_FREE(other_edges, struct bg_trimesh_edges);
+ }
+ } else {
+ /* fast path - exit on first error */
+ open_edges = bg_trimesh_excess_edges(num_edges, edge_list,
bg_trimesh_edge_exit, NULL);
+ }
+
+ bu_free(edge_list, "edge list");
+
+ bu_vls_printf(gib->vls, open_edges ? "1" : "0");
+
+ if (gib->gb->visualize) {
+ struct bu_vls sname = BU_VLS_INIT_ZERO;
+ bu_vls_sprintf(&sname, "_%s_open_edges", gib->gb->solid_name.c_str());
+ if (db_lookup(gib->gb->gedp->ged_wdbp->dbip, bu_vls_cstr(&sname),
LOOKUP_QUIET) != RT_DIR_NULL) {
+ dl_erasePathFromDisplay(gib->gb->gedp->ged_gdp->gd_headDisplay,
gib->gb->gedp->ged_wdbp->dbip, gib->gb->gedp->ged_free_vlist_callback,
bu_vls_cstr(&sname), 1, gib->gb->gedp->freesolid);
+ }
+ _ged_cvt_vlblock_to_solids(gib->gb->gedp, vbp, bu_vls_cstr(&sname), 0);
+ bu_vls_free(&sname);
+ }
+
+ return GED_OK;
+}
+
+
+extern "C" int
+_bot_cmd_solid(void *bs, int argc, const char **argv)
+{
+ const char *usage_string = "bot [options] <objname1> solid";
+ const char *purpose_string = "Check if BoT defines a topologically closed
solid";
+ if (_bot_check_msgs(bs, argc, argv, usage_string, purpose_string)) {
+ return GED_OK;
+ }
+
+ argc--;argv++;
+
+ struct _ged_bot_icheck *gib = (struct _ged_bot_icheck *)bs;
+
+ if (gib->gb->intern.idb_minor_type != DB5_MINORTYPE_BRLCAD_BOT) {
+ bu_vls_printf(gib->gb->gedp->ged_result_str, ": object %s is not of
type bot\n", gib->gb->solid_name.c_str());
+ return GED_ERROR;
+ }
+
+ struct rt_bot_internal *bot = (struct rt_bot_internal
*)(gib->gb->intern.idb_ptr);
+ struct bn_vlblock *vbp = gib->gb->vbp;
+ struct bg_trimesh_solid_errors errors = BG_TRIMESH_SOLID_ERRORS_INIT_NULL;
+ int not_solid;
+
+ if (bot->mode == RT_BOT_PLATE || bot->mode == RT_BOT_PLATE_NOCOS) {
+ bu_vls_printf(gib->vls, "1");
+ return GED_OK;
+ }
+
+ int num_vertices = (int)bot->num_vertices;
+ int num_faces = (int)bot->num_faces;
+
+ not_solid = bg_trimesh_solid2(num_vertices, num_faces, bot->vertices,
bot->faces, gib->gb->visualize ? &errors : NULL);
+ bu_vls_printf(gib->vls, "%d", (not_solid) ? 0 : 1);
+
+ if (not_solid && gib->gb->visualize) {
+ struct bg_trimesh_edges *degen_edges = NULL, *all_edges, *other_edges;
+ struct bg_trimesh_edges error_lists[4];
+ int num_lists = 0;
+
+ error_lists[num_lists++] = errors.unmatched;
+ error_lists[num_lists++] = errors.misoriented;
+ error_lists[num_lists++] = errors.excess;
+ if (errors.degenerate.count > 0) {
+ degen_edges = face_edges(errors.degenerate, bot);
+ error_lists[num_lists++] = *degen_edges;
+ }
+
+ all_edges = edges_from_bot(bot);
+ other_edges = edges_not_in_lists(*all_edges, error_lists, num_lists);
+ bg_free_trimesh_edges(all_edges);
+ BU_FREE(all_edges, struct bg_trimesh_edges);
+
+ struct bu_color red = BU_COLOR_INIT_ZERO;
+ bu_color_from_str(&red, "255/0/0");
+ struct bu_color yellow = BU_COLOR_INIT_ZERO;
+ bu_color_from_str(&yellow, "255/255/0");
+ struct bu_color orange = BU_COLOR_INIT_ZERO;
+ bu_color_from_str(&orange, "255/128/0");
+ struct bu_color purple = BU_COLOR_INIT_ZERO;
+ bu_color_from_str(&purple, "255/0/255");
+
+ draw_edges(vbp, bot, other_edges->count, other_edges->edges, &red);
+ draw_edges(vbp, bot, errors.unmatched.count, errors.unmatched.edges,
&yellow);
+ draw_edges(vbp, bot, errors.misoriented.count,
errors.misoriented.edges, &orange);
+ draw_edges(vbp, bot, errors.excess.count, errors.excess.edges, &purple);
+
+ if (errors.degenerate.count > 0) {
+ struct bu_color blue = BU_COLOR_INIT_ZERO;
+ bu_color_from_str(&blue, "0/0/255");
+ draw_edges(vbp, bot, degen_edges->count, degen_edges->edges, &blue);
+
+ bg_free_trimesh_edges(degen_edges);
+ BU_FREE(degen_edges, struct bg_trimesh_edges);
+ }
+ bg_free_trimesh_edges(other_edges);
+ BU_FREE(other_edges, struct bg_trimesh_edges);
+ bg_free_trimesh_solid_errors(&errors);
+
+ struct bu_vls sname = BU_VLS_INIT_ZERO;
+ bu_vls_sprintf(&sname, "_%s_not_solid", gib->gb->solid_name.c_str());
+ if (db_lookup(gib->gb->gedp->ged_wdbp->dbip, bu_vls_cstr(&sname),
LOOKUP_QUIET) != RT_DIR_NULL) {
+ dl_erasePathFromDisplay(gib->gb->gedp->ged_gdp->gd_headDisplay,
gib->gb->gedp->ged_wdbp->dbip, gib->gb->gedp->ged_free_vlist_callback,
bu_vls_cstr(&sname), 1, gib->gb->gedp->freesolid);
+ }
+ _ged_cvt_vlblock_to_solids(gib->gb->gedp, vbp, bu_vls_cstr(&sname), 0);
+ bu_vls_free(&sname);
+ }
+
+ return GED_OK;
+}
+
+static void
+_bot_check_help(struct _ged_bot_icheck *bs, int argc, const char **argv)
+{
+ struct _ged_bot_icheck *gb = (struct _ged_bot_icheck *)bs;
+ if (!argc || !argv) {
+ bu_vls_printf(gb->vls, "bot [options] <objname> check [subcommand]\n");
+ bu_vls_printf(gb->vls, "Available subcommands:\n");
+ const struct bu_cmdtab *ctp = NULL;
+ int ret;
+ const char *helpflag[2];
+ helpflag[1] = PURPOSEFLAG;
+ size_t maxcmdlen = 0;
+ for (ctp = gb->cmds; ctp->ct_name != (char *)NULL; ctp++) {
+ maxcmdlen = (maxcmdlen > strlen(ctp->ct_name)) ? maxcmdlen :
strlen(ctp->ct_name);
+ }
+ for (ctp = gb->cmds; ctp->ct_name != (char *)NULL; ctp++) {
+ bu_vls_printf(gb->vls, " %s%*s", ctp->ct_name, (int)(maxcmdlen -
strlen(ctp->ct_name)) + 2, " ");
+ helpflag[0] = ctp->ct_name;
+ bu_cmd(gb->cmds, 2, helpflag, 0, (void *)gb, &ret);
+ }
+ } else {
+ int ret;
+ const char *helpflag[2];
+ helpflag[0] = argv[0];
+ helpflag[1] = HELPFLAG;
+ bu_cmd(gb->cmds, 2, helpflag, 0, (void *)gb, &ret);
+ }
+}
+
+const struct bu_cmdtab _bot_check_cmds[] = {
+ { "degen_faces", _bot_cmd_degen_faces},
+ { "extra_edges", _bot_cmd_extra_edges},
+ { "flipped_edges", _bot_cmd_flipped_edges},
+ { "open_edges", _bot_cmd_open_edges},
+ { "solid", _bot_cmd_solid},
+ { (char *)NULL, NULL}
+};
+
+int
+_bot_cmd_check(void *bs, int argc, const char **argv)
+{
+ struct _ged_bot_info *gb = (struct _ged_bot_info *)bs;
+ struct _ged_bot_icheck gib;
+ gib.gb = gb;
+ gib.vls = gb->gedp->ged_result_str;
+ gib.cmds = _bot_check_cmds;
+
+
+ if (!argc) {
+ _bot_check_help(&gib, 0, NULL);
+ return GED_OK;
+ }
+
+ if (argc > 1 && BU_STR_EQUAL(argv[1], HELPFLAG)) {
+ argc--;argv++;
+ argc--;argv++;
+ _bot_check_help(&gib, argc, argv);
+ return GED_OK;
+ }
+
+ argc--; argv++;
+
+ // Must have valid subcommand to process
+ if (bu_cmd_valid(_bot_check_cmds, argv[0]) != BRLCAD_OK) {
+ bu_vls_printf(gib.vls, "invalid subcommand \"%s\" specified\n",
argv[0]);
+ _bot_check_help(&gib, 0, NULL);
+ return GED_ERROR;
+ }
+
+ int ret;
+ if (bu_cmd(_bot_check_cmds, argc, argv, 0, (void *)&gib, &ret) ==
BRLCAD_OK) {
+ return ret;
+ }
+ return GED_ERROR;
+}
+
+
+
+// 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/trunk/src/libged/bot/check.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
Added: brlcad/trunk/src/libged/bot/ged_bot.h
===================================================================
--- brlcad/trunk/src/libged/bot/ged_bot.h (rev 0)
+++ brlcad/trunk/src/libged/bot/ged_bot.h 2020-05-01 21:39:07 UTC (rev
75663)
@@ -0,0 +1,86 @@
+/* G E D _ B O T . H
+ * BRL-CAD
+ *
+ * Copyright (c) 2008-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 ged_bot.h
+ *
+ * Private header for libged bot cmd.
+ *
+ */
+
+#ifndef LIBGED_BREP_GED_PRIVATE_H
+#define LIBGED_BREP_GED_PRIVATE_H
+
+#include "common.h"
+
+#include <set>
+#include <string>
+#include <time.h>
+
+#include "bu/opt.h"
+#include "bn/plot3.h"
+#include "bu/color.h"
+#include "rt/db4.h"
+#include "raytrace.h"
+#include "rt/geom.h"
+#include "ged.h"
+
+__BEGIN_DECLS
+
+#define HELPFLAG "--print-help"
+#define PURPOSEFLAG "--print-purpose"
+
+struct _ged_bot_info {
+ struct ged *gedp = NULL;
+ struct rt_db_internal intern;
+ struct directory *dp = NULL;
+ struct bn_vlblock *vbp = NULL;
+ struct bu_color *color = NULL;
+ int verbosity;
+ int visualize;
+ std::string solid_name;
+ const struct bu_cmdtab *cmds = NULL;
+ struct bu_opt_desc *gopts = NULL;
+};
+
+/* defined in draw.c */
+extern void _ged_cvt_vlblock_to_solids(struct ged *gedp,
+ struct bn_vlblock *vbp,
+ const char *name,
+ int copy);
+
+int _bot_cmd_msgs(void *bs, int argc, const char **argv, const char *us, const
char *ps);
+
+int _bot_cmd_check(void *bs, int argc, const char **argv);
+
+int _bot_cmd_remesh(void *bs, int argc, const char **argv);
+
+__END_DECLS
+
+#endif /* LIBGED_BREP_GED_PRIVATE_H */
+
+/** @} */
+/*
+ * Local Variables:
+ * mode: C
+ * tab-width: 8
+ * indent-tabs-mode: t
+ * c-file-style: "stroustrup"
+ * End:
+ * ex: shiftwidth=4 tabstop=8
+ */
Property changes on: brlcad/trunk/src/libged/bot/ged_bot.h
___________________________________________________________________
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
Copied: brlcad/trunk/src/libged/bot/remesh.cpp (from rev 75662,
brlcad/trunk/src/libged/bot_remesh.cpp)
===================================================================
--- brlcad/trunk/src/libged/bot/remesh.cpp (rev 0)
+++ brlcad/trunk/src/libged/bot/remesh.cpp 2020-05-01 21:39:07 UTC (rev
75663)
@@ -0,0 +1,270 @@
+/* B O T _ R E M E S H . C P P
+ * BRL-CAD
+ *
+ * Copyright (c) 2019-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 libged/bot_remesh.cpp
+ *
+ * The bot "remesh" sub-command.
+ *
+ */
+
+#include "common.h"
+
+#ifdef OPENVDB_ABI_VERSION_NUMBER
+# include <openvdb/openvdb.h>
+# include <openvdb/tools/VolumeToMesh.h>
+# include <openvdb/tools/MeshToVolume.h>
+#endif /* OPENVDB_ABI_VERSION_NUMBER */
+
+#include "vmath.h"
+#include "bu/str.h"
+#include "rt/db5.h"
+#include "rt/db_internal.h"
+#include "rt/db_io.h"
+#include "rt/geom.h"
+#include "rt/wdb.h"
+#include "ged/commands.h"
+#include "ged/database.h"
+#include "ged/objects.h"
+#include "./ged_bot.h"
+
+
+#ifdef OPENVDB_ABI_VERSION_NUMBER
+
+struct botDataAdapter {
+ struct rt_bot_internal *bot;
+
+ size_t polygonCount() const {
+ return bot->num_faces;
+ };
+ size_t pointCount() const {
+ return bot->num_vertices;
+ };
+ size_t vertexCount(size_t) const {
+ return 3;
+ };
+ void getIndexSpacePoint(size_t n, size_t v, openvdb::Vec3d& pos) const {
+ int idx = bot->faces[(n*3)+v];
+ pos[X] = bot->vertices[(idx*3)+X];
+ pos[Y] = bot->vertices[(idx*3)+Y];
+ pos[Z] = bot->vertices[(idx*3)+Z];
+ return;
+ };
+
+ /* constructor */
+ botDataAdapter(struct rt_bot_internal *bip) : bot(bip) {}
+};
+
+
+static bool
+bot_remesh(struct ged *UNUSED(gedp), struct rt_bot_internal *bot, double
voxelSize)
+{
+ const float exteriorBandWidth = 10.0;
+ const float interiorBandWidth = std::numeric_limits<float>::max();
+
+ struct botDataAdapter bda(bot);
+
+ openvdb::initialize();
+
+ bu_log("...voxelizing");
+
+ openvdb::math::Transform::Ptr xform =
openvdb::math::Transform::createLinearTransform(voxelSize);
+ openvdb::FloatGrid::Ptr bot2vol =
openvdb::tools::meshToVolume<openvdb::FloatGrid, botDataAdapter>(bda, *xform,
exteriorBandWidth, interiorBandWidth);
+
+#if 0
+ openvdb::io::File file("mesh.vdb");
+ openvdb::GridPtrVec grids;
+ grids.push_back(bot2vol);
+ file.write(grids);
+ file.close();
+ return false;
+#endif
+
+ bu_log("...devoxelizing");
+
+ std::vector<openvdb::Vec3s> points;
+ std::vector<openvdb::Vec3I> triangles;
+ std::vector<openvdb::Vec4I> quadrilaterals;
+ openvdb::tools::volumeToMesh<openvdb::FloatGrid>(*bot2vol, points,
triangles, quadrilaterals);
+
+ bu_log("...storing");
+
+ if (bot->vertices) {
+ bu_free(bot->vertices, "vertices");
+ bot->num_vertices = 0;
+ }
+ if (bot->faces) {
+ bu_free(bot->faces, "faces");
+ bot->num_faces = 0;
+ }
+ if (bot->normals) {
+ bu_free(bot->normals, "normals");
+ }
+ if (bot->face_normals) {
+ bu_free(bot->face_normals, "face normals");
+ }
+
+ bot->num_vertices = points.size();
+ bot->vertices = (fastf_t *)bu_malloc(bot->num_vertices *
ELEMENTS_PER_POINT * sizeof(fastf_t), "vertices");
+ for (size_t i = 0; i < points.size(); i++) {
+ bot->vertices[(i*3)+X] = points[i].x();
+ bot->vertices[(i*3)+Y] = points[i].y();
+ bot->vertices[(i*3)+Z] = points[i].z();
+ }
+ bot->num_faces = triangles.size() + (quadrilaterals.size() * 2);
+ bot->faces = (int *)bu_malloc(bot->num_faces * 3 * sizeof(int),
"triangles");
+ for (size_t i = 0; i < triangles.size(); i++) {
+ bot->faces[(i*3)+X] = triangles[i].x();
+ bot->faces[(i*3)+Y] = triangles[i].y();
+ bot->faces[(i*3)+Z] = triangles[i].z();
+ }
+ size_t ntri = triangles.size();
+ for (size_t i = 0; i < quadrilaterals.size(); i++) {
+ bot->faces[((ntri+i)*3)+X] = quadrilaterals[i][0];
+ bot->faces[((ntri+i)*3)+Y] = quadrilaterals[i][1];
+ bot->faces[((ntri+i)*3)+Z] = quadrilaterals[i][2];
+
+ bot->faces[((ntri+i+1)*3)+X] = quadrilaterals[i][0];
+ bot->faces[((ntri+i+1)*3)+Y] = quadrilaterals[i][2];
+ bot->faces[((ntri+i+1)*3)+Z] = quadrilaterals[i][3];
+ }
+
+ bu_log("...done!\n");
+
+ return (points.size() > 0);
+}
+
+#else /* OPENVDB_ABI_VERSION_NUMBER */
+
+static bool
+bot_remesh(struct ged *gedp, struct rt_bot_internal *UNUSED(bot), double
UNUSED(voxelSize))
+{
+ bu_vls_printf(gedp->ged_result_str,
+ "WARNING: BoT remeshing is unavailable.\n"
+ "BRL-CAD needs to be compiled with OpenVDB support.\n"
+ "(cmake -DBRLCAD_ENABLE_OPENVDB=ON)\n");
+ return false;
+}
+
+#endif /* OPENVDB_ABI_VERSION_NUMBER */
+
+
+
+
+extern "C" int
+_bot_cmd_remesh(void *bs, int argc, const char **argv)
+{
+ const char *usage_string = "bot [options] <objname> remesh [output_bot]";
+ const char *purpose_string = "Store a remeshed version of the BoT in
object <output_bot>";
+ if (_bot_cmd_msgs(bs, argc, argv, usage_string, purpose_string)) {
+ return GED_OK;
+ }
+
+ struct _ged_bot_info *gb = (struct _ged_bot_info *)bs;
+
+ struct ged *gedp = gb->gedp;
+
+ if (gb->intern.idb_minor_type != DB5_MINORTYPE_BRLCAD_BOT) {
+ bu_vls_printf(gb->gedp->ged_result_str, ": object %s is not of type
bot\n", gb->solid_name.c_str());
+ return GED_ERROR;
+ }
+
+ const char *input_bot_name = gb->dp->d_namep;
+ const char *output_bot_name;
+ struct directory *dp_input;
+ struct directory *dp_output;
+ struct rt_bot_internal *input_bot;
+
+ GED_CHECK_DATABASE_OPEN(gedp, GED_ERROR);
+ GED_CHECK_READ_ONLY(gedp, GED_ERROR);
+ GED_CHECK_ARGC_GT_0(gedp, argc, GED_ERROR);
+
+ dp_input = dp_output = RT_DIR_NULL;
+
+ /* initialize result */
+ bu_vls_trunc(gedp->ged_result_str, 0);
+
+ /* must be wanting help */
+ if (argc == 1) {
+ bu_vls_printf(gedp->ged_result_str, "%s\n%s", usage_string,
purpose_string);
+ return GED_HELP;
+ }
+
+ /* check that we are using a version 5 database */
+ if (db_version(gedp->ged_wdbp->dbip) < 5) {
+ bu_vls_printf(gedp->ged_result_str,
+ "ERROR: Unable to remesh the current (v%d) database.\n"
+ "Use \"dbupgrade\" to upgrade this database to the
current version.\n",
+ db_version(gedp->ged_wdbp->dbip));
+ return GED_ERROR;
+ }
+
+ if (argc > 3) {
+ bu_vls_printf(gedp->ged_result_str, "ERROR: unexpected arguments
encountered\n");
+ bu_vls_printf(gedp->ged_result_str, "%s\n%s", usage_string,
purpose_string);
+ return GED_ERROR;
+ }
+
+ output_bot_name = input_bot_name;
+ if (argc > 1)
+ output_bot_name = (char *)argv[1];
+
+ if (!BU_STR_EQUAL(input_bot_name, output_bot_name)) {
+ GED_CHECK_EXISTS(gedp, output_bot_name, LOOKUP_QUIET, GED_ERROR);
+ }
+
+ if (gb->intern.idb_major_type != DB5_MAJORTYPE_BRLCAD ||
gb->intern.idb_minor_type != DB5_MINORTYPE_BRLCAD_BOT) {
+ bu_vls_printf(gedp->ged_result_str, "%s is not a BOT primitive\n",
input_bot_name);
+ return GED_ERROR;
+ }
+
+ input_bot = (struct rt_bot_internal *)gb->intern.idb_ptr;
+ RT_BOT_CK_MAGIC(input_bot);
+
+ bu_log("INPUT BoT has %zu vertices and %zu faces\n",
input_bot->num_vertices, input_bot->num_faces);
+
+ /* TODO: stash a backup if overwriting the original */
+
+ bool ok = bot_remesh(gedp, input_bot, 50);
+ if (!ok) {
+ return GED_ERROR;
+ }
+
+ bu_log("OUTPUT BoT has %zu vertices and %zu faces\n",
input_bot->num_vertices, input_bot->num_faces);
+
+ if (BU_STR_EQUAL(input_bot_name, output_bot_name)) {
+ dp_output = dp_input;
+ } else {
+ GED_DB_DIRADD(gedp, dp_output, output_bot_name, RT_DIR_PHONY_ADDR, 0,
RT_DIR_SOLID, (void *)&gb->intern.idb_type, GED_ERROR);
+ }
+
+ GED_DB_PUT_INTERNAL(gedp, dp_output, &gb->intern,
gedp->ged_wdbp->wdb_resp, GED_ERROR);
+
+ return GED_OK;
+}
+
+
+/*
+ * Local Variables:
+ * tab-width: 8
+ * mode: C
+ * indent-tabs-mode: t
+ * c-file-style: "stroustrup"
+ * End:
+ * ex: shiftwidth=4 tabstop=8
+ */
Deleted: brlcad/trunk/src/libged/bot.c
===================================================================
--- brlcad/trunk/src/libged/bot.c 2020-05-01 17:33:34 UTC (rev 75662)
+++ brlcad/trunk/src/libged/bot.c 2020-05-01 21:39:07 UTC (rev 75663)
@@ -1,709 +0,0 @@
-/* B O T . C
- * BRL-CAD
- *
- * Copyright (c) 2008-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 libged/bot.c
- *
- * Bot command for simple bot primitive operations.
- *
- */
-
-#include "common.h"
-
-#include <stdlib.h>
-#include <ctype.h>
-#include <string.h>
-
-#include "bu/opt.h"
-#include "bu/sort.h"
-#include "bg/chull.h"
-#include "bg/trimesh.h"
-#include "rt/geom.h"
-#include "wdb.h"
-#include "./ged_private.h"
-
-
-HIDDEN void
-_bot_show_help(struct ged *gedp, struct bu_opt_desc *d)
-{
- struct bu_vls str = BU_VLS_INIT_ZERO;
- char *option_help;
-
- bu_vls_sprintf(&str, "Usage: bot [options] [subcommand] [subcommand
arguments]\n\n");
-
- if ((option_help = bu_opt_describe(d, NULL))) {
- bu_vls_printf(&str, "Options:\n%s\n", option_help);
- bu_free(option_help, "help str");
- }
- bu_vls_printf(&str, "Subcommands:\n\n");
- bu_vls_printf(&str, " get
(faces|minEdge|maxEdge|orientation|type|vertices) <bot>\n");
- bu_vls_printf(&str, " - Get specific BoT information.\n");
- bu_vls_printf(&str, " check
(solid|degen_faces|open_edges|extra_edges|flipped_edges) <bot>\n");
- bu_vls_printf(&str, " - Check the BoT for problems (see bot_check man
page).\n");
- bu_vls_printf(&str, " chull <bot> <output_bot>\n");
- bu_vls_printf(&str, " - Store the BoT's convex hull in
<output_bot>.\n");
- bu_vls_printf(&str, " remesh <bot> <output_bot>\n");
- bu_vls_printf(&str, " - Store a remeshed version of <bot> in
<output_bot>.\n");
-/*
- TODO: document 'isect'
- bu_vls_printf(&str, " isect <bot1> <bot2>\n");
- bu_vls_printf(&str, " - intersection of <bot1> and <bot2>.\n");
-
- TODO: add/merge other bot_* commands as subcommands
-*/
- bu_vls_printf(&str, "\n");
-
- bu_vls_vlscat(gedp->ged_result_str, &str);
- bu_vls_free(&str);
-}
-
-/* for bsearch() */
-HIDDEN int
-edge_compare(const void *a, const void *b)
-{
- const int *edge_a = (int *)a;
- const int *edge_b = (int *)b;
- int diff = edge_a[0] - edge_b[0];
- return diff ? diff : edge_a[1] - edge_b[1];
-}
-
-/* for bu_sort() */
-HIDDEN int
-edge_cmp(const void *a, const void *b, void *UNUSED(context))
-{
- return edge_compare(a, b);
-}
-
-HIDDEN int
-is_edge_in_list(int edge[2], struct bg_trimesh_edges list)
-{
- return (bsearch(edge, list.edges, list.count, sizeof(int) * 2,
edge_compare) != NULL);
-}
-
-HIDDEN int
- is_edge_in_lists(int edge[2], struct bg_trimesh_edges lists[], int num_lists)
-{
- int i;
- for (i = 0; i < num_lists; ++i) {
- if (is_edge_in_list(edge, lists[i])) {
- return 1;
- }
- }
- return 0;
-}
-
-HIDDEN struct bg_trimesh_edges*
-make_edges(int edge_count)
-{
- struct bg_trimesh_edges *edges;
- BU_ALLOC(edges, struct bg_trimesh_edges);
- edges->count = 0;
- edges->edges = (int *)bu_malloc(edge_count * 2 * sizeof(int), "make
edges");
- return edges;
-}
-
-HIDDEN void
-copy_edge(int dst[2], int src[2])
-{
- dst[0] = src[0];
- dst[1] = src[1];
-}
-
-HIDDEN void
-append_edge(struct bg_trimesh_edges *list, int edge[2])
-{
- copy_edge(&list->edges[list->count * 2], edge);
- ++(list->count);
-}
-
-HIDDEN void
-append_edge_if_not_in_lists(struct bg_trimesh_edges *dst, int edge[2], struct
bg_trimesh_edges lists[], int num_lists)
-{
- if (!is_edge_in_lists(edge, lists, num_lists)) {
- append_edge(dst, edge);
- }
-}
-
-HIDDEN struct bg_trimesh_edges*
-edges_not_in_lists(struct bg_trimesh_edges all, struct bg_trimesh_edges
lists[], int num_lists)
-{
- int i;
- struct bg_trimesh_edges *remaining = make_edges(all.count);
-
- for (i = 0; i < all.count; ++i) {
- append_edge_if_not_in_lists(remaining, &all.edges[i * 2], lists,
num_lists);
- }
- return remaining;
-}
-
-HIDDEN struct bg_trimesh_edges*
-edges_from_half_edges(struct bg_trimesh_halfedge edge_list[], int num_edges)
-{
- int i;
- struct bg_trimesh_edges *edges = make_edges(num_edges);
-
- for (i = 0; i < num_edges; ++i) {
- int half_edge[2];
- half_edge[0] = edge_list[i].va;
- half_edge[1] = edge_list[i].vb;
- append_edge_if_not_in_lists(edges, half_edge, edges, 1);
- }
- return edges;
-}
-
-HIDDEN void
-standardize_edge(int edge[2])
-{
- if (edge[1] < edge[0]) {
- int tmp = edge[0];
- edge[0] = edge[1];
- edge[1] = tmp;
- }
-}
-
-HIDDEN void
-append_face_edges(struct bg_trimesh_edges *edges, int face[3])
-{
- int i, edge[2];
- for (i = 0; i < 3; ++i) {
- edge[0] = face[i];
- edge[1] = face[(i + 1) % 3];
- standardize_edge(edge);
- append_edge(edges, edge);
- }
-}
-
-HIDDEN struct bg_trimesh_edges*
-non_unique_face_edges(struct bg_trimesh_faces faces, struct rt_bot_internal
*bot)
-{
- int i;
- struct bg_trimesh_edges *edges = make_edges(faces.count * 3);
-
- for (i = 0; i < faces.count; ++i) {
- append_face_edges(edges, &bot->faces[faces.faces[i] * 3]);
- }
- bu_sort(edges->edges, edges->count, sizeof(int) * 2, edge_cmp, NULL);
- return edges;
-}
-
-HIDDEN struct bg_trimesh_edges*
-face_edges(struct bg_trimesh_faces faces, struct rt_bot_internal *bot)
-{
- int i;
- struct bg_trimesh_edges *unique_edges = make_edges(faces.count * 3);
- struct bg_trimesh_edges *all_edges = non_unique_face_edges(faces, bot);
-
- for (i = 0; i < all_edges->count; ++i) {
- append_edge_if_not_in_lists(unique_edges, &all_edges->edges[i * 2],
unique_edges, 1);
- }
- bg_free_trimesh_edges(all_edges);
- BU_FREE(all_edges, struct bg_trimesh_edges);
-
- return unique_edges;
-}
-
-HIDDEN struct bg_trimesh_faces*
-make_faces(int num_faces)
-{
- struct bg_trimesh_faces *faces;
- BU_ALLOC(faces, struct bg_trimesh_faces);
-
- faces->count = 0;
- faces->faces = (int *)bu_malloc(sizeof(int) * num_faces, "make faces");
- return faces;
-}
-
-HIDDEN struct bg_trimesh_faces*
-faces_from_bot(struct rt_bot_internal *bot)
-{
- int i;
- struct bg_trimesh_faces *faces = make_faces((int)bot->num_faces);
- faces->count = (int)bot->num_faces;
- for (i = 0; i < faces->count; ++i) {
- faces->faces[i] = i;
- }
- return faces;
-}
-
-HIDDEN struct bg_trimesh_edges*
-edges_from_bot(struct rt_bot_internal *bot)
-{
- struct bg_trimesh_faces *faces = faces_from_bot(bot);
- struct bg_trimesh_edges *edges = face_edges(*faces, bot);
-
- bg_free_trimesh_faces(faces);
- BU_FREE(faces, struct bg_trimesh_faces);
-
- return edges;
-}
-
-HIDDEN void
-draw_edges(struct ged *gedp, struct rt_bot_internal *bot, int num_edges, int
edges[], int draw_color[3], const char *draw_name)
-{
- int curr_edge = 0;
- struct bu_list *vhead;
- point_t a, b;
- struct bn_vlblock *vbp;
- struct bu_list local_vlist;
-
- BU_LIST_INIT(&local_vlist);
- vbp = bn_vlblock_init(&local_vlist, 32);
-
- /* Clear any previous visual */
- if (db_lookup(gedp->ged_wdbp->dbip, draw_name, LOOKUP_QUIET) !=
RT_DIR_NULL)
- dl_erasePathFromDisplay(gedp->ged_gdp->gd_headDisplay,
gedp->ged_wdbp->dbip, gedp->ged_free_vlist_callback, draw_name, 1,
gedp->freesolid);
-
- for (curr_edge = 0; curr_edge < num_edges; curr_edge++) {
- int p1 = edges[curr_edge*2];
- int p2 = edges[curr_edge*2+1];
- VSET(a, bot->vertices[p1*3], bot->vertices[p1*3+1],
bot->vertices[p1*3+2]);
- VSET(b, bot->vertices[p2*3], bot->vertices[p2*3+1],
bot->vertices[p2*3+2]);
- vhead = bn_vlblock_find(vbp, draw_color[0], draw_color[1],
draw_color[2]);
- BN_ADD_VLIST(vbp->free_vlist_hd, vhead, a, BN_VLIST_LINE_MOVE);
- BN_ADD_VLIST(vbp->free_vlist_hd, vhead, b, BN_VLIST_LINE_DRAW);
- }
-
- _ged_cvt_vlblock_to_solids(gedp, vbp, draw_name, 0);
- bn_vlist_cleanup(&local_vlist);
- bn_vlblock_free(vbp);
-}
-
-HIDDEN int
-bot_check(struct ged *gedp, int argc, const char *argv[], struct bu_opt_desc
*d, struct rt_db_internal *ip, int visualize_results)
-{
- const char *check = argv[1];
- const char * const *sub, *subcommands[] = {"solid", "degen_faces",
"open_edges", "extra_edges", "flipped_edges", NULL};
- struct rt_bot_internal *bot = (struct rt_bot_internal *)ip->idb_ptr;
- struct bg_trimesh_halfedge *edge_list;
- int (*edge_test)(int, struct bg_trimesh_halfedge *, bg_edge_error_funct_t,
void *);
- int num_vertices, num_faces, num_edges;
- int found;
- int red[] = {255, 0, 0};
- int blue[] = {0, 0, 255};
- int yellow[] = {255, 255, 0};
- int orange[] = {255, 128, 0};
- int purple[] = {255, 0, 255};
-
- /* must be wanting help */
- if (argc < 2) {
- _bot_show_help(gedp, d);
- rt_db_free_internal(ip);
- return GED_ERROR;
- }
-
- num_vertices = (int)bot->num_vertices;
- num_faces = (int)bot->num_faces;
- num_edges = num_faces * 3;
-
- if (argc < 3 || BU_STR_EQUAL(check, "solid")) {
- struct bg_trimesh_solid_errors errors =
BG_TRIMESH_SOLID_ERRORS_INIT_NULL;
- int not_solid;
-
- if (bot->mode == RT_BOT_PLATE || bot->mode == RT_BOT_PLATE_NOCOS) {
- bu_vls_printf(gedp->ged_result_str, "1");
- rt_db_free_internal(ip);
- return GED_OK;
- }
-
- not_solid = bg_trimesh_solid2(num_vertices, num_faces, bot->vertices,
bot->faces, visualize_results ? &errors : NULL);
- bu_vls_printf(gedp->ged_result_str, not_solid ? "0" : "1");
-
- if (not_solid && visualize_results) {
- struct bg_trimesh_edges *degen_edges = NULL, *all_edges,
*other_edges;
- struct bg_trimesh_edges error_lists[4];
- int num_lists = 0;
-
- error_lists[num_lists++] = errors.unmatched;
- error_lists[num_lists++] = errors.misoriented;
- error_lists[num_lists++] = errors.excess;
- if (errors.degenerate.count > 0) {
- degen_edges = face_edges(errors.degenerate, bot);
- error_lists[num_lists++] = *degen_edges;
- }
-
- all_edges = edges_from_bot(bot);
- other_edges = edges_not_in_lists(*all_edges, error_lists,
num_lists);
- bg_free_trimesh_edges(all_edges);
- BU_FREE(all_edges, struct bg_trimesh_edges);
-
- draw_edges(gedp, bot, other_edges->count, other_edges->edges, red,
"other faces");
- draw_edges(gedp, bot, errors.unmatched.count,
errors.unmatched.edges, yellow, "unmatched edges");
- draw_edges(gedp, bot, errors.misoriented.count,
errors.misoriented.edges, orange, "misoriented edges");
- draw_edges(gedp, bot, errors.excess.count, errors.excess.edges,
purple, "excess edges");
-
- if (errors.degenerate.count > 0) {
- draw_edges(gedp, bot, degen_edges->count, degen_edges->edges,
blue, "degenerate faces");
-
- bg_free_trimesh_edges(degen_edges);
- BU_FREE(degen_edges, struct bg_trimesh_edges);
- }
- bg_free_trimesh_edges(other_edges);
- BU_FREE(other_edges, struct bg_trimesh_edges);
- bg_free_trimesh_solid_errors(&errors);
- }
- rt_db_free_internal(ip);
- return GED_OK;
- }
-
- /* check for one of the individual tests */
- found = 0;
- sub = subcommands;
- for (; *sub != NULL; ++sub) {
- if (BU_STR_EQUAL(check, *sub)) {
- found = 1;
- break;
- }
- }
- if (!found) {
- bu_vls_printf(gedp->ged_result_str, "check: %s is not a recognized
check subcommand!\n", check);
- rt_db_free_internal(ip);
- return GED_ERROR;
- }
-
- /* face test */
- if (BU_STR_EQUAL(check, "degen_faces")) {
- struct bg_trimesh_faces degenerate = BG_TRIMESH_FACES_INIT_NULL;
- struct bg_trimesh_edges *degen_edges, *all_edges, *other_edges;
- int degenerate_faces = 0;
-
- if (visualize_results) {
- /* first pass - count errors */
- degenerate_faces = bg_trimesh_degenerate_faces(num_faces,
bot->faces, bg_trimesh_face_continue, NULL);
-
- if (degenerate_faces) {
- /* second pass - generate error faces array and draw it */
- degenerate.count = 0;
- degenerate.faces = (int *)bu_calloc(degenerate_faces,
sizeof(int), "degenerate faces");
- bg_trimesh_degenerate_faces(num_faces, bot->faces,
bg_trimesh_face_gather, °enerate);
-
- degen_edges = face_edges(degenerate, bot);
- bg_free_trimesh_faces(°enerate);
-
- all_edges = edges_from_bot(bot);
- other_edges = edges_not_in_lists(*all_edges, degen_edges, 1);
- bg_free_trimesh_edges(all_edges);
- BU_FREE(all_edges, struct bg_trimesh_edges);
-
- draw_edges(gedp, bot, degen_edges->count, degen_edges->edges,
yellow, "degenerate faces");
- draw_edges(gedp, bot, other_edges->count, other_edges->edges,
red, "othererate faces");
-
- bg_free_trimesh_edges(degen_edges);
- BU_FREE(degen_edges, struct bg_trimesh_edges);
- bg_free_trimesh_edges(other_edges);
- BU_FREE(other_edges, struct bg_trimesh_edges);
- }
- } else {
- /* fast path - exit on first error */
- degenerate_faces = bg_trimesh_degenerate_faces(num_faces,
bot->faces, bg_trimesh_face_exit, NULL);
- }
-
- bu_vls_printf(gedp->ged_result_str, degenerate_faces ? "1" : "0");
-
- rt_db_free_internal(ip);
- return GED_OK;
- }
-
- /* must be doing one of the edge tests */
-
- /* generate half-edge list */
- if (!(edge_list = bg_trimesh_generate_edge_list(num_faces, bot->faces))) {
- rt_db_free_internal(ip);
- bu_vls_printf(gedp->ged_result_str, "ERROR: failed to generate an edge
list\n");
- return GED_ERROR;
- }
-
- /* select edge test */
- if (BU_STR_EQUAL(check, "open_edges")) {
- edge_test = bg_trimesh_unmatched_edges;
- } else if (BU_STR_EQUAL(check, "flipped_edges")) {
- edge_test = bg_trimesh_misoriented_edges;
- } else if (BU_STR_EQUAL(check, "extra_edges")) {
- edge_test = bg_trimesh_excess_edges;
- } else {
- bu_vls_printf(gedp->ged_result_str, "ERROR: unrecognized edge test
[%s]\n", check);
- return GED_ERROR;
- }
-
- if (visualize_results) {
- /* first pass - count errors */
- struct bg_trimesh_edges error_edges = BG_TRIMESH_EDGES_INIT_NULL;
- struct bg_trimesh_edges *all_edges, *other_edges;
-
- found = edge_test(num_edges, edge_list, bg_trimesh_edge_continue, NULL);
-
- if (found) {
- /* second pass - generate error edge array and draw it */
- error_edges.count = 0;
- error_edges.edges = (int *)bu_calloc(found * 2, sizeof(int), "error
edges");
- found = edge_test(num_edges, edge_list, bg_trimesh_edge_gather,
&error_edges);
-
- all_edges = edges_from_half_edges(edge_list, num_edges);
- other_edges = edges_not_in_lists(*all_edges, &error_edges, 1);
- bg_free_trimesh_edges(all_edges);
- BU_FREE(all_edges, struct bg_trimesh_edges);
-
- draw_edges(gedp, bot, error_edges.count, error_edges.edges, yellow,
"error edges");
- draw_edges(gedp, bot, other_edges->count, other_edges->edges, red,
"other edges");
-
- bg_free_trimesh_edges(&error_edges);
- bg_free_trimesh_edges(other_edges);
- BU_FREE(other_edges, struct bg_trimesh_edges);
- }
- } else {
- /* fast path - exit on first error */
- found = edge_test(num_edges, edge_list, bg_trimesh_edge_exit, NULL);
- }
-
- bu_free(edge_list, "edge list");
-
- bu_vls_printf(gedp->ged_result_str, found ? "1" : "0");
- rt_db_free_internal(ip);
- return GED_OK;
-}
-
-int
-ged_bot(struct ged *gedp, int argc, const char *argv[])
-{
- struct directory *bot_dp;
- struct rt_db_internal intern;
- struct rt_bot_internal *bot;
- const char *cmd = argv[0];
- const char *sub = NULL;
- const char *arg = NULL;
- const char *primitive = NULL;
- const char *primitive_2 = NULL;
- size_t len;
- fastf_t tmp;
- fastf_t propVal;
- int i;
- int print_help = 0;
- int visualize_results = 0;
- int opt_ret = 0;
- int opt_argc;
- struct bu_opt_desc d[3];
- const char * const bot_subcommands[] = {"check", "chull", "get", "isect",
"remesh", NULL};
- BU_OPT(d[0], "h", "help", "", NULL, &print_help, "Print help
and exit");
- BU_OPT(d[1], "V", "visualize", "", NULL, &visualize_results, "Use
subcommand's 3D visualization.");
- BU_OPT_NULL(d[2]);
-
- GED_CHECK_DATABASE_OPEN(gedp, GED_ERROR);
- GED_CHECK_READ_ONLY(gedp, GED_ERROR);
- GED_CHECK_ARGC_GT_0(gedp, argc, GED_ERROR);
-
- /* initialize result */
- bu_vls_trunc(gedp->ged_result_str, 0);
-
- /* must be wanting help */
- if (argc < 3) {
- _bot_show_help(gedp, d);
- return GED_ERROR;
- }
-
- /* See if we have any options to deal with. Once we hit a subcommand,
we're done */
- opt_argc = argc;
- for (i = 1; i < argc; ++i) {
- const char * const *subcmd = bot_subcommands;
-
- for (; *subcmd != NULL; ++subcmd) {
- if (BU_STR_EQUAL(argv[i], *subcmd)) {
- opt_argc = i;
- i = argc;
- break;
- }
- }
- }
-
- if (opt_argc >= argc) {
- /* no subcommand given */
- _bot_show_help(gedp, d);
- return GED_ERROR;
- }
-
- if (opt_argc > 1) {
- /* parse standard options */
- opt_ret = bu_opt_parse(NULL, opt_argc, argv, d);
- if (opt_ret < 0) _bot_show_help(gedp, d);
- }
-
- /* shift past standard options to subcommand args */
- argc -= opt_argc;
- argv = &argv[opt_argc];
-
- if (argc < 2) {
- _bot_show_help(gedp, d);
- return GED_ERROR;
- }
-
- /* determine subcommand */
- sub = argv[0];
- len = strlen(sub);
- if (bu_strncmp(sub, "get", len) == 0) {
- primitive = argv[argc - 1];
- } else if (bu_strncmp(sub, "chull", len) == 0) {
- primitive = argv[1];
- primitive_2 = argv[2];
- } else if (bu_strncmp(sub, "isect", len) == 0) {
- primitive = argv[1];
- primitive_2 = argv[2];
- } else if (bu_strncmp(sub, "check", len) == 0) {
- primitive = argv[argc - 1];
- } else if (bu_strncmp(sub, "remesh", len) == 0) {
- primitive = argv[1];
- primitive_2 = argv[2];
- } else {
- bu_vls_printf(gedp->ged_result_str, "%s: %s is not a known
subcommand!", cmd, sub);
- return GED_ERROR;
- }
-
- /* get bot */
- GED_DB_LOOKUP(gedp, bot_dp, primitive, LOOKUP_NOISY, GED_ERROR &
GED_QUIET);
- GED_DB_GET_INTERNAL(gedp, &intern, bot_dp, bn_mat_identity,
&rt_uniresource, GED_ERROR);
-
- if (intern.idb_major_type != DB5_MAJORTYPE_BRLCAD || intern.idb_minor_type
!= DB5_MINORTYPE_BRLCAD_BOT) {
- bu_vls_printf(gedp->ged_result_str, "%s: %s is not a BOT solid!", cmd,
primitive);
- rt_db_free_internal(&intern);
- return GED_ERROR;
- }
-
- bot = (struct rt_bot_internal *)intern.idb_ptr;
- RT_BOT_CK_MAGIC(bot);
-
- if (bu_strncmp(sub, "get", len) == 0) {
- arg = argv[1];
- propVal = rt_bot_propget(bot, arg);
-
- /* print result string */
- if (!EQUAL(propVal, -1.0)) {
-
- tmp = (int) propVal;
-
- /* int result */
- if (EQUAL(propVal, tmp)) {
- bu_vls_printf(gedp->ged_result_str, "%d", (int) propVal);
- }
-
- /* float result */
- else {
- bu_vls_printf(gedp->ged_result_str, "%f", propVal);
- }
- } else {
- bu_vls_printf(gedp->ged_result_str, "%s: %s is not a valid
argument!", sub, arg);
- rt_db_free_internal(&intern);
- return GED_ERROR;
- }
-
- } else if (bu_strncmp(sub, "chull", len) == 0) {
-
- int retval = 0;
- int fc = 0;
- int vc = 0;
- point_t *vert_array;
- int *faces;
- unsigned char err = 0;
-
- /* must be wanting help */
- if (argc < 3) {
- _bot_show_help(gedp, d);
- rt_db_free_internal(&intern);
- return GED_ERROR;
- }
-
- retval = bg_3d_chull(&faces, &fc, &vert_array, &vc, (const point_t
*)bot->vertices, (int)bot->num_vertices);
-
- if (retval != 3) {
- rt_db_free_internal(&intern);
- return GED_ERROR;
- }
-
- retval = mk_bot(gedp->ged_wdbp, primitive_2, RT_BOT_SOLID, RT_BOT_CCW,
err, vc, fc, (fastf_t *)vert_array, faces, NULL, NULL);
-
- bu_free(faces, "free faces");
- bu_free(vert_array, "free verts");
-
- if (retval) {
- rt_db_free_internal(&intern);
- return GED_ERROR;
- }
-
- } else if (bu_strncmp(sub, "isect", len) == 0) {
-
- struct directory *bot_dp_2;
- struct rt_db_internal intern_2;
- struct rt_bot_internal *bot_2;
-
- /* must be wanting help */
- if (argc < 3) {
- _bot_show_help(gedp, d);
- rt_db_free_internal(&intern);
- return GED_ERROR;
- }
-
- GED_DB_LOOKUP(gedp, bot_dp_2, primitive_2, LOOKUP_NOISY, GED_ERROR &
GED_QUIET);
- GED_DB_GET_INTERNAL(gedp, &intern_2, bot_dp_2, bn_mat_identity,
&rt_uniresource, GED_ERROR);
-
- if (intern_2.idb_major_type != DB5_MAJORTYPE_BRLCAD ||
intern_2.idb_minor_type != DB5_MINORTYPE_BRLCAD_BOT) {
- bu_vls_printf(gedp->ged_result_str, "%s: %s is not a BOT solid!",
cmd, primitive_2);
- rt_db_free_internal(&intern_2);
- rt_db_free_internal(&intern);
- return GED_ERROR;
- }
- bot_2 = (struct rt_bot_internal *)intern_2.idb_ptr;
-
- {
- int fc_1 = (int)bot->num_faces;
- int fc_2 = (int)bot_2->num_faces;
- int vc_1 = (int)bot->num_vertices;
- int vc_2 = (int)bot_2->num_vertices;
- point_t *verts_1 = (point_t *)bot->vertices;
- point_t *verts_2 = (point_t *)bot_2->vertices;
- int *faces_1 = bot->faces;
- int *faces_2 = bot_2->faces;
-
- (void)bg_trimesh_isect(NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL,
- faces_1, fc_1, verts_1, vc_1, faces_2, fc_2, verts_2, vc_2);
-
- rt_db_free_internal(&intern);
- rt_db_free_internal(&intern_2);
- return GED_OK;
- }
-
- } else if (bu_strncmp(sub, "check", len) == 0) {
-
- return bot_check(gedp, argc, argv, d, &intern, visualize_results);
-
- } else if (bu_strncmp(sub, "remesh", len) == 0) {
-
- return ged_bot_remesh(gedp, argc, argv);
-
- }
-
- rt_db_free_internal(&intern);
-
- return GED_OK;
-}
-
-
-/*
- * Local Variables:
- * tab-width: 8
- * mode: C
- * indent-tabs-mode: t
- * c-file-style: "stroustrup"
- * End:
- * ex: shiftwidth=4 tabstop=8
- */
Deleted: brlcad/trunk/src/libged/bot_remesh.cpp
===================================================================
--- brlcad/trunk/src/libged/bot_remesh.cpp 2020-05-01 17:33:34 UTC (rev
75662)
+++ brlcad/trunk/src/libged/bot_remesh.cpp 2020-05-01 21:39:07 UTC (rev
75663)
@@ -1,260 +0,0 @@
-/* B O T _ R E M E S H . C P P
- * BRL-CAD
- *
- * Copyright (c) 2019-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 libged/bot_remesh.cpp
- *
- * The bot "remesh" sub-command.
- *
- */
-
-#include "common.h"
-
-#ifdef OPENVDB_ABI_VERSION_NUMBER
-# include <openvdb/openvdb.h>
-# include <openvdb/tools/VolumeToMesh.h>
-# include <openvdb/tools/MeshToVolume.h>
-#endif /* OPENVDB_ABI_VERSION_NUMBER */
-
-#include "vmath.h"
-#include "bu/str.h"
-#include "rt/db5.h"
-#include "rt/db_internal.h"
-#include "rt/db_io.h"
-#include "rt/geom.h"
-#include "rt/wdb.h"
-#include "ged/commands.h"
-#include "ged/database.h"
-#include "ged/objects.h"
-
-
-#ifdef OPENVDB_ABI_VERSION_NUMBER
-
-struct botDataAdapter {
- struct rt_bot_internal *bot;
-
- size_t polygonCount() const {
- return bot->num_faces;
- };
- size_t pointCount() const {
- return bot->num_vertices;
- };
- size_t vertexCount(size_t) const {
- return 3;
- };
- void getIndexSpacePoint(size_t n, size_t v, openvdb::Vec3d& pos) const {
- int idx = bot->faces[(n*3)+v];
- pos[X] = bot->vertices[(idx*3)+X];
- pos[Y] = bot->vertices[(idx*3)+Y];
- pos[Z] = bot->vertices[(idx*3)+Z];
- return;
- };
-
- /* constructor */
- botDataAdapter(struct rt_bot_internal *bip) : bot(bip) {}
-};
-
-
-static bool
-bot_remesh(struct ged *UNUSED(gedp), struct rt_bot_internal *bot, double
voxelSize)
-{
- const float exteriorBandWidth = 10.0;
- const float interiorBandWidth = std::numeric_limits<float>::max();
-
- struct botDataAdapter bda(bot);
-
- openvdb::initialize();
-
- bu_log("...voxelizing");
-
- openvdb::math::Transform::Ptr xform =
openvdb::math::Transform::createLinearTransform(voxelSize);
- openvdb::FloatGrid::Ptr bot2vol =
openvdb::tools::meshToVolume<openvdb::FloatGrid, botDataAdapter>(bda, *xform,
exteriorBandWidth, interiorBandWidth);
-
-#if 0
- openvdb::io::File file("mesh.vdb");
- openvdb::GridPtrVec grids;
- grids.push_back(bot2vol);
- file.write(grids);
- file.close();
- return false;
-#endif
-
- bu_log("...devoxelizing");
-
- std::vector<openvdb::Vec3s> points;
- std::vector<openvdb::Vec3I> triangles;
- std::vector<openvdb::Vec4I> quadrilaterals;
- openvdb::tools::volumeToMesh<openvdb::FloatGrid>(*bot2vol, points,
triangles, quadrilaterals);
-
- bu_log("...storing");
-
- if (bot->vertices) {
- bu_free(bot->vertices, "vertices");
- bot->num_vertices = 0;
- }
- if (bot->faces) {
- bu_free(bot->faces, "faces");
- bot->num_faces = 0;
- }
- if (bot->normals) {
- bu_free(bot->normals, "normals");
- }
- if (bot->face_normals) {
- bu_free(bot->face_normals, "face normals");
- }
-
- bot->num_vertices = points.size();
- bot->vertices = (fastf_t *)bu_malloc(bot->num_vertices *
ELEMENTS_PER_POINT * sizeof(fastf_t), "vertices");
- for (size_t i = 0; i < points.size(); i++) {
- bot->vertices[(i*3)+X] = points[i].x();
- bot->vertices[(i*3)+Y] = points[i].y();
- bot->vertices[(i*3)+Z] = points[i].z();
- }
- bot->num_faces = triangles.size() + (quadrilaterals.size() * 2);
- bot->faces = (int *)bu_malloc(bot->num_faces * 3 * sizeof(int),
"triangles");
- for (size_t i = 0; i < triangles.size(); i++) {
- bot->faces[(i*3)+X] = triangles[i].x();
- bot->faces[(i*3)+Y] = triangles[i].y();
- bot->faces[(i*3)+Z] = triangles[i].z();
- }
- size_t ntri = triangles.size();
- for (size_t i = 0; i < quadrilaterals.size(); i++) {
- bot->faces[((ntri+i)*3)+X] = quadrilaterals[i][0];
- bot->faces[((ntri+i)*3)+Y] = quadrilaterals[i][1];
- bot->faces[((ntri+i)*3)+Z] = quadrilaterals[i][2];
-
- bot->faces[((ntri+i+1)*3)+X] = quadrilaterals[i][0];
- bot->faces[((ntri+i+1)*3)+Y] = quadrilaterals[i][2];
- bot->faces[((ntri+i+1)*3)+Z] = quadrilaterals[i][3];
- }
-
- bu_log("...done!\n");
-
- return (points.size() > 0);
-}
-
-#else /* OPENVDB_ABI_VERSION_NUMBER */
-
-static bool
-bot_remesh(struct ged *gedp, struct rt_bot_internal *UNUSED(bot), double
UNUSED(voxelSize))
-{
- bu_vls_printf(gedp->ged_result_str,
- "WARNING: BoT remeshing is unavailable.\n"
- "BRL-CAD needs to be compiled with OpenVDB support.\n"
- "(cmake -DBRLCAD_ENABLE_OPENVDB=ON)\n");
- return false;
-}
-
-#endif /* OPENVDB_ABI_VERSION_NUMBER */
-
-
-int
-ged_bot_remesh(struct ged *gedp, int argc, const char *argv[])
-{
- static const char *usage = "input.bot [output.bot]";
-
- char *input_bot_name;
- char *output_bot_name;
- struct directory *dp_input;
- struct directory *dp_output;
- struct rt_bot_internal *input_bot;
- struct rt_db_internal intern;
-
- GED_CHECK_DATABASE_OPEN(gedp, GED_ERROR);
- GED_CHECK_READ_ONLY(gedp, GED_ERROR);
- GED_CHECK_ARGC_GT_0(gedp, argc, GED_ERROR);
-
- dp_input = dp_output = RT_DIR_NULL;
-
- /* initialize result */
- bu_vls_trunc(gedp->ged_result_str, 0);
-
- /* must be wanting help */
- if (argc == 1) {
- bu_vls_printf(gedp->ged_result_str, "Usage: %s %s", argv[0], usage);
- return GED_HELP;
- }
-
- /* check that we are using a version 5 database */
- if (db_version(gedp->ged_wdbp->dbip) < 5) {
- bu_vls_printf(gedp->ged_result_str,
- "ERROR: Unable to remesh the current (v%d) database.\n"
- "Use \"dbupgrade\" to upgrade this database to the
current version.\n",
- db_version(gedp->ged_wdbp->dbip));
- return GED_ERROR;
- }
-
- if (argc > 3) {
- bu_vls_printf(gedp->ged_result_str, "ERROR: unexpected arguments
encountered\n");
- bu_vls_printf(gedp->ged_result_str, "Usage: %s %s", argv[0], usage);
- return GED_ERROR;
- }
-
- input_bot_name = output_bot_name = (char *)argv[1];
- if (argc > 2)
- output_bot_name = (char *)argv[2];
-
- if (!BU_STR_EQUAL(input_bot_name, output_bot_name)) {
- GED_CHECK_EXISTS(gedp, output_bot_name, LOOKUP_QUIET, GED_ERROR);
- }
-
- GED_DB_LOOKUP(gedp, dp_input, input_bot_name, LOOKUP_QUIET, GED_ERROR);
- GED_DB_GET_INTERNAL(gedp, &intern, dp_input, NULL,
gedp->ged_wdbp->wdb_resp, GED_ERROR);
-
- if (intern.idb_major_type != DB5_MAJORTYPE_BRLCAD || intern.idb_minor_type
!= DB5_MINORTYPE_BRLCAD_BOT) {
- bu_vls_printf(gedp->ged_result_str, "%s is not a BOT primitive\n",
input_bot_name);
- rt_db_free_internal(&intern);
- return GED_ERROR;
- }
-
- input_bot = (struct rt_bot_internal *)intern.idb_ptr;
- RT_BOT_CK_MAGIC(input_bot);
-
- bu_log("INPUT BoT has %zu vertices and %zu faces\n",
input_bot->num_vertices, input_bot->num_faces);
-
- /* TODO: stash a backup if overwriting the original */
-
- bool ok = bot_remesh(gedp, input_bot, 50);
- if (!ok) {
- return GED_ERROR;
- }
-
- bu_log("OUTPUT BoT has %zu vertices and %zu faces\n",
input_bot->num_vertices, input_bot->num_faces);
-
- if (BU_STR_EQUAL(input_bot_name, output_bot_name)) {
- dp_output = dp_input;
- } else {
- GED_DB_DIRADD(gedp, dp_output, output_bot_name, RT_DIR_PHONY_ADDR, 0,
RT_DIR_SOLID, (void *)&intern.idb_type, GED_ERROR);
- }
-
- GED_DB_PUT_INTERNAL(gedp, dp_output, &intern, gedp->ged_wdbp->wdb_resp,
GED_ERROR);
- rt_db_free_internal(&intern);
-
- return GED_OK;
-}
-
-
-/*
- * Local Variables:
- * tab-width: 8
- * mode: C
- * indent-tabs-mode: t
- * c-file-style: "stroustrup"
- * End:
- * ex: shiftwidth=4 tabstop=8
- */
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