Revision: 76392
http://sourceforge.net/p/brlcad/code/76392
Author: starseeker
Date: 2020-07-21 17:17:07 +0000 (Tue, 21 Jul 2020)
Log Message:
-----------
Add the GED_EXPORT definitions so gsh can load the plugins successfully
Modified Paths:
--------------
brlcad/branches/gedplugins/src/libged/CMakeLists.txt
brlcad/branches/gedplugins/src/libged/bot/ged_bot.h
brlcad/branches/gedplugins/src/libged/brep/csg.cpp
brlcad/branches/gedplugins/src/libged/brep/ged_brep.h
brlcad/branches/gedplugins/src/libged/check/check_private.h
brlcad/branches/gedplugins/src/libged/edbot/edbot.c
brlcad/branches/gedplugins/src/libged/editit/editit.c
brlcad/branches/gedplugins/src/libged/edpipe/edpipe.c
brlcad/branches/gedplugins/src/libged/ged_private.h
brlcad/branches/gedplugins/src/libged/nmg_cmface/nmg_cmface.c
brlcad/branches/gedplugins/src/libged/nmg_collapse/nmg_collapse.c
brlcad/branches/gedplugins/src/libged/nmg_fix_normals/nmg_fix_normals.c
brlcad/branches/gedplugins/src/libged/nmg_kill_f/nmg_kill_f.c
brlcad/branches/gedplugins/src/libged/nmg_kill_v/nmg_kill_v.c
brlcad/branches/gedplugins/src/libged/nmg_make_v/nmg_make_v.c
brlcad/branches/gedplugins/src/libged/nmg_mm/nmg_mm.c
brlcad/branches/gedplugins/src/libged/nmg_move_v/nmg_move_v.c
brlcad/branches/gedplugins/src/libged/nmg_simplify/nmg_simplify.c
brlcad/branches/gedplugins/src/libged/pnts_util.h
brlcad/branches/gedplugins/src/libged/qray.h
Added Paths:
-----------
brlcad/branches/gedplugins/src/libged/columns.c
brlcad/branches/gedplugins/src/libged/display_list.c
Removed Paths:
-------------
brlcad/branches/gedplugins/src/libged/columns/
brlcad/branches/gedplugins/src/libged/display_list/
Modified: brlcad/branches/gedplugins/src/libged/CMakeLists.txt
===================================================================
--- brlcad/branches/gedplugins/src/libged/CMakeLists.txt 2020-07-21
16:36:56 UTC (rev 76391)
+++ brlcad/branches/gedplugins/src/libged/CMakeLists.txt 2020-07-21
17:17:07 UTC (rev 76392)
@@ -50,8 +50,8 @@
exec.cpp
ged_init.cpp
libfuncs/libfuncs.c
- columns/columns.c
- display_list/display_list.c
+ columns.c
+ display_list.c
draw_calc.cpp
edbot/edbot.c
edit_metaball/edit_metaball.c
Modified: brlcad/branches/gedplugins/src/libged/bot/ged_bot.h
===================================================================
--- brlcad/branches/gedplugins/src/libged/bot/ged_bot.h 2020-07-21 16:36:56 UTC
(rev 76391)
+++ brlcad/branches/gedplugins/src/libged/bot/ged_bot.h 2020-07-21 17:17:07 UTC
(rev 76392)
@@ -68,11 +68,11 @@
int _bot_cmd_msgs(void *bs, int argc, const char **argv, const char *us, const
char *ps);
-int _bot_cmd_extrude(void *bs, int argc, const char **argv);
+GED_EXPORT int _bot_cmd_extrude(void *bs, int argc, const char **argv);
-int _bot_cmd_check(void *bs, int argc, const char **argv);
+GED_EXPORT int _bot_cmd_check(void *bs, int argc, const char **argv);
-int _bot_cmd_remesh(void *bs, int argc, const char **argv);
+GED_EXPORT int _bot_cmd_remesh(void *bs, int argc, const char **argv);
__END_DECLS
Modified: brlcad/branches/gedplugins/src/libged/brep/csg.cpp
===================================================================
--- brlcad/branches/gedplugins/src/libged/brep/csg.cpp 2020-07-21 16:36:56 UTC
(rev 76391)
+++ brlcad/branches/gedplugins/src/libged/brep/csg.cpp 2020-07-21 17:17:07 UTC
(rev 76392)
@@ -748,27 +748,28 @@
return 0;
}
-extern "C" int
-_ged_brep_to_csg(struct ged *gedp, const char *dp_name, int verify)
-{
- struct bu_attribute_value_set ito = BU_AVS_INIT_ZERO; /* islands to
objects */
- int ret = 0;
- struct bu_vls log = BU_VLS_INIT_ZERO;
- struct rt_wdb *wdbp = gedp->ged_wdbp;
- struct directory *dp = db_lookup(wdbp->dbip, dp_name, LOOKUP_QUIET);
- if (dp == RT_DIR_NULL) return GED_ERROR;
+extern "C" {
+ GED_EXPORT int
+ _ged_brep_to_csg(struct ged *gedp, const char *dp_name, int verify)
+ {
+ struct bu_attribute_value_set ito = BU_AVS_INIT_ZERO; /* islands to
objects */
+ int ret = 0;
+ struct bu_vls log = BU_VLS_INIT_ZERO;
+ struct rt_wdb *wdbp = gedp->ged_wdbp;
+ struct directory *dp = db_lookup(wdbp->dbip, dp_name, LOOKUP_QUIET);
+ if (dp == RT_DIR_NULL) return GED_ERROR;
- if (dp->d_flags & RT_DIR_COMB) {
- ret = comb_to_csg(gedp, &log, &ito, dp, verify) ? GED_ERROR : GED_OK;
- } else {
- ret = _obj_brep_to_csg(gedp, &log, &ito, dp, verify, NULL) ? GED_ERROR
: GED_OK;
- }
+ if (dp->d_flags & RT_DIR_COMB) {
+ ret = comb_to_csg(gedp, &log, &ito, dp, verify) ? GED_ERROR :
GED_OK;
+ } else {
+ ret = _obj_brep_to_csg(gedp, &log, &ito, dp, verify, NULL) ?
GED_ERROR : GED_OK;
+ }
- bu_vls_sprintf(gedp->ged_result_str, "%s", bu_vls_addr(&log));
- bu_vls_free(&log);
- return ret;
+ bu_vls_sprintf(gedp->ged_result_str, "%s", bu_vls_addr(&log));
+ bu_vls_free(&log);
+ return ret;
+ }
}
-
// Local Variables:
// tab-width: 8
// mode: C++
Modified: brlcad/branches/gedplugins/src/libged/brep/ged_brep.h
===================================================================
--- brlcad/branches/gedplugins/src/libged/brep/ged_brep.h 2020-07-21
16:36:56 UTC (rev 76391)
+++ brlcad/branches/gedplugins/src/libged/brep/ged_brep.h 2020-07-21
17:17:07 UTC (rev 76392)
@@ -100,23 +100,23 @@
int copy);
-extern int _ged_brep_to_csg(struct ged *gedp, const char *obj_name, int
verify);
+GED_EXPORT extern int _ged_brep_to_csg(struct ged *gedp, const char *obj_name,
int verify);
-extern int brep_info(struct bu_vls *vls, const ON_Brep *brep, int argc, const
char **argv);
-extern int brep_pick(struct _ged_brep_info *gb, int argc, const char **argv);
-extern int brep_plot(struct _ged_brep_info *gb, int argc, const char **argv);
-extern int brep_tikz(struct _ged_brep_info *gb, const char *outfile);
-extern int brep_valid(struct bu_vls *vls, struct rt_db_internal *intern, int
argc, const char **argv);
+GED_EXPORT extern int brep_info(struct bu_vls *vls, const ON_Brep *brep, int
argc, const char **argv);
+GED_EXPORT extern int brep_pick(struct _ged_brep_info *gb, int argc, const
char **argv);
+GED_EXPORT extern int brep_plot(struct _ged_brep_info *gb, int argc, const
char **argv);
+GED_EXPORT extern int brep_tikz(struct _ged_brep_info *gb, const char
*outfile);
+GED_EXPORT extern int brep_valid(struct bu_vls *vls, struct rt_db_internal
*intern, int argc, const char **argv);
-extern int brep_conversion(struct rt_db_internal* in, struct rt_db_internal*
out, const struct db_i *dbip);
-extern int brep_conversion_comb(struct rt_db_internal *old_internal, const
char *name, const char *suffix, struct rt_wdb *wdbp, fastf_t local2mm);
+GED_EXPORT extern int brep_conversion(struct rt_db_internal* in, struct
rt_db_internal* out, const struct db_i *dbip);
+GED_EXPORT extern int brep_conversion_comb(struct rt_db_internal
*old_internal, const char *name, const char *suffix, struct rt_wdb *wdbp,
fastf_t local2mm);
-extern int brep_intersect_point_point(struct rt_db_internal *intern1, struct
rt_db_internal *intern2, int i, int j);
-extern int brep_intersect_point_curve(struct rt_db_internal *intern1, struct
rt_db_internal *intern2, int i, int j);
-extern int brep_intersect_point_surface(struct rt_db_internal *intern1, struct
rt_db_internal *intern2, int i, int j);
-extern int brep_intersect_curve_curve(struct rt_db_internal *intern1, struct
rt_db_internal *intern2, int i, int j);
-extern int brep_intersect_curve_surface(struct rt_db_internal *intern1, struct
rt_db_internal *intern2, int i, int j);
-extern int brep_intersect_surface_surface(struct rt_db_internal *intern1,
struct rt_db_internal *intern2, int i, int j, struct bn_vlblock *vbp);
+GED_EXPORT extern int brep_intersect_point_point(struct rt_db_internal
*intern1, struct rt_db_internal *intern2, int i, int j);
+GED_EXPORT extern int brep_intersect_point_curve(struct rt_db_internal
*intern1, struct rt_db_internal *intern2, int i, int j);
+GED_EXPORT extern int brep_intersect_point_surface(struct rt_db_internal
*intern1, struct rt_db_internal *intern2, int i, int j);
+GED_EXPORT extern int brep_intersect_curve_curve(struct rt_db_internal
*intern1, struct rt_db_internal *intern2, int i, int j);
+GED_EXPORT extern int brep_intersect_curve_surface(struct rt_db_internal
*intern1, struct rt_db_internal *intern2, int i, int j);
+GED_EXPORT extern int brep_intersect_surface_surface(struct rt_db_internal
*intern1, struct rt_db_internal *intern2, int i, int j, struct bn_vlblock *vbp);
using namespace brlcad;
void
Modified: brlcad/branches/gedplugins/src/libged/check/check_private.h
===================================================================
--- brlcad/branches/gedplugins/src/libged/check/check_private.h 2020-07-21
16:36:56 UTC (rev 76391)
+++ brlcad/branches/gedplugins/src/libged/check/check_private.h 2020-07-21
17:17:07 UTC (rev 76392)
@@ -225,25 +225,25 @@
int tnobjs,
struct check_parameters *options);
-extern check_functions_t check_adj_air;
+GED_EXPORT extern check_functions_t check_adj_air;
-extern check_functions_t check_centroid;
+GED_EXPORT extern check_functions_t check_centroid;
-extern check_functions_t check_exp_air;
+GED_EXPORT extern check_functions_t check_exp_air;
-extern check_functions_t check_gap;
+GED_EXPORT extern check_functions_t check_gap;
-extern check_functions_t check_mass;
+GED_EXPORT extern check_functions_t check_mass;
-extern check_functions_t check_moments;
+GED_EXPORT extern check_functions_t check_moments;
-extern check_functions_t check_overlaps;
+GED_EXPORT extern check_functions_t check_overlaps;
-extern check_functions_t check_surf_area;
+GED_EXPORT extern check_functions_t check_surf_area;
-extern check_functions_t check_unconf_air;
+GED_EXPORT extern check_functions_t check_unconf_air;
-extern check_functions_t check_volume;
+GED_EXPORT extern check_functions_t check_volume;
__END_DECLS
#endif /* LIBGED_CHECK_PRIVATE_H */
Copied: brlcad/branches/gedplugins/src/libged/columns.c (from rev 76391,
brlcad/branches/gedplugins/src/libged/columns/columns.c)
===================================================================
--- brlcad/branches/gedplugins/src/libged/columns.c
(rev 0)
+++ brlcad/branches/gedplugins/src/libged/columns.c 2020-07-21 17:17:07 UTC
(rev 76392)
@@ -0,0 +1,90 @@
+/* C O L U M N S . C
+ * BRL-CAD
+ *
+ * Copyright (c) 1985-2020 United States Government as represented by
+ * the U.S. Army Research Laboratory.
+ *
+ * This program is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU Lesser General Public License
+ * version 2.1 as published by the Free Software Foundation.
+ *
+ * This program is distributed in the hope that it will be useful, but
+ * WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+ * Lesser General Public License for more details.
+ *
+ * You should have received a copy of the GNU Lesser General Public
+ * License along with this file; see the file named COPYING for more
+ * information.
+ */
+/** @file libged/columns.c
+ *
+ * A set of routines for printing columns of data.
+ *
+ */
+
+/* TODO: It should be lowered to libbu. */
+
+#include "common.h"
+
+#include <stdlib.h>
+#include <string.h>
+
+
+#include "vmath.h"
+#include "raytrace.h"
+#include "rt/db4.h"
+#include "./ged_private.h"
+
+
+static int col_count; /* names listed on current line */
+static int col_len; /* length of previous name */
+#define TERMINAL_WIDTH 80 /* XXX */
+#define COLUMNS ((TERMINAL_WIDTH + NAMESIZE - 1) / NAMESIZE)
+
+void
+vls_col_item(
+ struct bu_vls *str,
+ const char *cp)
+{
+ /* Output newline if last column printed. */
+ if (col_count >= COLUMNS || (col_len+NAMESIZE-1) >= TERMINAL_WIDTH) {
+ /* line now full */
+ bu_vls_putc(str, '\n');
+ col_count = 0;
+ } else if (col_count != 0) {
+ /* Space over before starting new column */
+ do {
+ bu_vls_putc(str, ' ');
+ col_len++;
+ } while ((col_len % NAMESIZE) != 0);
+ }
+ /* Output string and save length for next tab. */
+ col_len = 0;
+ while (*cp != '\0') {
+ bu_vls_putc(str, *cp);
+ ++cp;
+ ++col_len;
+ }
+ col_count++;
+}
+
+
+void
+vls_col_eol(struct bu_vls *str)
+{
+ if (col_count != 0) /* partial line */
+ bu_vls_putc(str, '\n');
+ col_count = 0;
+ col_len = 0;
+}
+
+/*
+ * Local Variables:
+ * mode: C
+ * tab-width: 8
+ * indent-tabs-mode: t
+ * c-file-style: "stroustrup"
+ * End:
+ * ex: shiftwidth=4 tabstop=8
+ */
Copied: brlcad/branches/gedplugins/src/libged/display_list.c (from rev 76391,
brlcad/branches/gedplugins/src/libged/display_list/display_list.c)
===================================================================
--- brlcad/branches/gedplugins/src/libged/display_list.c
(rev 0)
+++ brlcad/branches/gedplugins/src/libged/display_list.c 2020-07-21
17:17:07 UTC (rev 76392)
@@ -0,0 +1,2549 @@
+/* D I S P L A Y _ L I S 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/display_list.c
+ *
+ * Collect display list manipulation logic here as it is refactored.
+ *
+ */
+
+#include "common.h"
+
+#include <stdlib.h>
+#include <string.h>
+
+#include "bu/ptbl.h"
+#include "bu/str.h"
+#include "bu/color.h"
+#include "bn/plot3.h"
+
+#include "rt/solid.h"
+#include "./ged_private.h"
+
+/* defined in draw_calc.cpp */
+extern fastf_t brep_est_avg_curve_len(struct rt_brep_internal *bi);
+extern void createDListSolid(struct solid *sp);
+
+struct display_list *
+dl_addToDisplay(struct bu_list *hdlp, struct db_i *dbip,
+ const char *name)
+{
+ struct directory *dp = NULL;
+ struct display_list *gdlp = NULL;
+ char *cp = NULL;
+ int found_namepath = 0;
+ struct db_full_path namepath;
+
+ cp = strrchr(name, '/');
+ if (!cp)
+ cp = (char *)name;
+ else
+ ++cp;
+
+ if ((dp = db_lookup(dbip, cp, LOOKUP_NOISY)) == RT_DIR_NULL) {
+ gdlp = GED_DISPLAY_LIST_NULL;
+ goto end;
+ }
+
+ if (db_string_to_path(&namepath, dbip, name) == 0)
+ found_namepath = 1;
+
+ /* Make sure name is not already in the list */
+ gdlp = BU_LIST_NEXT(display_list, hdlp);
+ while (BU_LIST_NOT_HEAD(gdlp, hdlp)) {
+ if (BU_STR_EQUAL(name, bu_vls_addr(&gdlp->dl_path)))
+ goto end;
+
+ if (found_namepath) {
+ struct db_full_path gdlpath;
+
+ if (db_string_to_path(&gdlpath, dbip, bu_vls_addr(&gdlp->dl_path))
== 0) {
+ if (db_full_path_match_top(&gdlpath, &namepath)) {
+ db_free_full_path(&gdlpath);
+ goto end;
+ }
+
+ db_free_full_path(&gdlpath);
+ }
+ }
+
+ gdlp = BU_LIST_PNEXT(display_list, gdlp);
+ }
+
+ BU_ALLOC(gdlp, struct display_list);
+ BU_LIST_INIT(&gdlp->l);
+ BU_LIST_INSERT(hdlp, &gdlp->l);
+ BU_LIST_INIT(&gdlp->dl_headSolid);
+ gdlp->dl_dp = (void *)dp;
+ bu_vls_init(&gdlp->dl_path);
+ bu_vls_printf(&gdlp->dl_path, "%s", name);
+
+end:
+ if (found_namepath)
+ db_free_full_path(&namepath);
+
+ return gdlp;
+}
+
+
+void
+headsolid_split(struct bu_list *hdlp, struct db_i *dbip, struct solid *sp, int
newlen)
+{
+ int savelen;
+ struct display_list *new_gdlp;
+ char *pathname;
+
+ savelen = sp->s_fullpath.fp_len;
+ sp->s_fullpath.fp_len = newlen;
+ pathname = db_path_to_string(&sp->s_fullpath);
+ sp->s_fullpath.fp_len = savelen;
+
+ new_gdlp = dl_addToDisplay(hdlp, dbip, pathname);
+ bu_free((void *)pathname, "headsolid_split pathname");
+
+ BU_LIST_DEQUEUE(&sp->l);
+ BU_LIST_INSERT(&new_gdlp->dl_headSolid, &sp->l);
+}
+
+
+
+int
+headsolid_splitGDL(struct bu_list *hdlp, struct db_i *dbip, struct
display_list *gdlp, struct db_full_path *path)
+{
+ struct solid *sp;
+ struct solid *nsp;
+ int newlen = path->fp_len + 1;
+
+ if (BU_LIST_IS_EMPTY(&gdlp->dl_headSolid)) return 0;
+
+ if (newlen < 3) {
+ while (BU_LIST_WHILE(sp, solid, &gdlp->dl_headSolid)) {
+ headsolid_split(hdlp, dbip, sp, newlen);
+ }
+ } else {
+ sp = BU_LIST_NEXT(solid, &gdlp->dl_headSolid);
+ while (BU_LIST_NOT_HEAD(sp, &gdlp->dl_headSolid)) {
+ nsp = BU_LIST_PNEXT(solid, sp);
+ if (db_full_path_match_top(path, &sp->s_fullpath)) {
+ headsolid_split(hdlp, dbip, sp, newlen);
+ }
+ sp = nsp;
+ }
+
+ --path->fp_len;
+ headsolid_splitGDL(hdlp, dbip, gdlp, path);
+ ++path->fp_len;
+ }
+
+ return 1;
+}
+
+
+int
+dl_bounding_sph(struct bu_list *hdlp, vect_t *min, vect_t *max, int pflag)
+{
+ struct display_list *gdlp;
+ struct display_list *next_gdlp;
+ struct solid *sp;
+ vect_t minus, plus;
+ int is_empty = 1;
+
+ VSETALL((*min), INFINITY);
+ VSETALL((*max), -INFINITY);
+
+ /* calculate the bounding for of all solids being displayed */
+ gdlp = BU_LIST_NEXT(display_list, hdlp);
+ while (BU_LIST_NOT_HEAD(gdlp, hdlp)) {
+ next_gdlp = BU_LIST_PNEXT(display_list, gdlp);
+
+ FOR_ALL_SOLIDS(sp, &gdlp->dl_headSolid) {
+ /* Skip pseudo-solids unless pflag is set */
+ if (!pflag &&
+ sp->s_fullpath.fp_names != (struct directory **)0 &&
+ sp->s_fullpath.fp_names[0] != (struct directory *)0 &&
+ sp->s_fullpath.fp_names[0]->d_addr == RT_DIR_PHONY_ADDR)
+ continue;
+
+ minus[X] = sp->s_center[X] - sp->s_size;
+ minus[Y] = sp->s_center[Y] - sp->s_size;
+ minus[Z] = sp->s_center[Z] - sp->s_size;
+ VMIN((*min), minus);
+ plus[X] = sp->s_center[X] + sp->s_size;
+ plus[Y] = sp->s_center[Y] + sp->s_size;
+ plus[Z] = sp->s_center[Z] + sp->s_size;
+ VMAX((*max), plus);
+
+ is_empty = 0;
+ }
+
+ gdlp = next_gdlp;
+ }
+
+ return is_empty;
+}
+
+/*
+ * Erase/remove the display list item from headDisplay if path matches the
list item's path.
+ *
+ */
+void
+dl_erasePathFromDisplay(struct bu_list *hdlp,
+ struct db_i *dbip, void (*callback)(unsigned int, int),
+ const char *path, int allow_split, struct solid *freesolid)
+{
+ struct display_list *gdlp;
+ struct display_list *next_gdlp;
+ struct display_list *last_gdlp;
+ struct solid *sp;
+ struct directory *dp;
+ struct db_full_path subpath;
+ int found_subpath;
+
+ if (db_string_to_path(&subpath, dbip, path) == 0)
+ found_subpath = 1;
+ else
+ found_subpath = 0;
+
+ gdlp = BU_LIST_NEXT(display_list, hdlp);
+ last_gdlp = BU_LIST_LAST(display_list, hdlp);
+ while (BU_LIST_NOT_HEAD(gdlp, hdlp)) {
+ next_gdlp = BU_LIST_PNEXT(display_list, gdlp);
+
+ if (BU_STR_EQUAL(path, bu_vls_addr(&gdlp->dl_path))) {
+ if (callback != GED_FREE_VLIST_CALLBACK_PTR_NULL) {
+
+ /* We can't assume the display lists are contiguous */
+ FOR_ALL_SOLIDS(sp, &gdlp->dl_headSolid) {
+ (*callback)(BU_LIST_FIRST(solid,
&gdlp->dl_headSolid)->s_dlist, 1);
+ }
+ }
+
+ /* Free up the solids list associated with this display list */
+ while (BU_LIST_WHILE(sp, solid, &gdlp->dl_headSolid)) {
+ if (sp) {
+ dp = FIRST_SOLID(sp);
+ RT_CK_DIR(dp);
+ if (dp->d_addr == RT_DIR_PHONY_ADDR) {
+ (void)db_dirdelete(dbip, dp);
+ }
+
+ BU_LIST_DEQUEUE(&sp->l);
+ FREE_SOLID(sp, &freesolid->l);
+ }
+ }
+
+ BU_LIST_DEQUEUE(&gdlp->l);
+ bu_vls_free(&gdlp->dl_path);
+ BU_FREE(gdlp, struct display_list);
+
+ break;
+ } else if (found_subpath) {
+ int need_split = 0;
+ struct solid *nsp;
+
+ sp = BU_LIST_NEXT(solid, &gdlp->dl_headSolid);
+ while (BU_LIST_NOT_HEAD(sp, &gdlp->dl_headSolid)) {
+ nsp = BU_LIST_PNEXT(solid, sp);
+
+ if (db_full_path_match_top(&subpath, &sp->s_fullpath)) {
+ if (callback != GED_FREE_VLIST_CALLBACK_PTR_NULL)
+ (*callback)(sp->s_dlist, 1);
+
+ BU_LIST_DEQUEUE(&sp->l);
+ FREE_SOLID(sp, &freesolid->l);
+ need_split = 1;
+ }
+
+ sp = nsp;
+ }
+
+ if (BU_LIST_IS_EMPTY(&gdlp->dl_headSolid)) {
+ BU_LIST_DEQUEUE(&gdlp->l);
+ bu_vls_free(&gdlp->dl_path);
+ BU_FREE(gdlp, struct display_list);
+ } else if (allow_split && need_split) {
+ BU_LIST_DEQUEUE(&gdlp->l);
+
+ --subpath.fp_len;
+ (void)headsolid_splitGDL(hdlp, dbip, gdlp, &subpath);
+ ++subpath.fp_len;
+
+ /* Free up the display list */
+ bu_vls_free(&gdlp->dl_path);
+ BU_FREE(gdlp, struct display_list);
+ }
+ }
+
+ if (gdlp == last_gdlp)
+ gdlp = (struct display_list *)hdlp;
+ else
+ gdlp = next_gdlp;
+ }
+
+ if (found_subpath)
+ db_free_full_path(&subpath);
+}
+
+
+HIDDEN void
+eraseAllSubpathsFromSolidList(struct display_list *gdlp,
+ struct db_full_path *subpath,
+ void (*callback)(unsigned int, int),
+ const int skip_first, struct solid *freesolid)
+{
+ struct solid *sp;
+ struct solid *nsp;
+
+ sp = BU_LIST_NEXT(solid, &gdlp->dl_headSolid);
+ while (BU_LIST_NOT_HEAD(sp, &gdlp->dl_headSolid)) {
+ nsp = BU_LIST_PNEXT(solid, sp);
+ if (db_full_path_subset(&sp->s_fullpath, subpath, skip_first)) {
+ if (callback != GED_FREE_VLIST_CALLBACK_PTR_NULL)
+ (*callback)(sp->s_dlist, 1);
+
+ BU_LIST_DEQUEUE(&sp->l);
+ FREE_SOLID(sp, &freesolid->l);
+ }
+ sp = nsp;
+ }
+}
+
+
+/*
+ * Erase/remove display list item from headDisplay if name is found anywhere
along item's path with
+ * the exception that the first path element is skipped if skip_first is true.
+ *
+ * Note - name is not expected to contain path separators.
+ *
+ */
+void
+_dl_eraseAllNamesFromDisplay(struct bu_list *hdlp, struct db_i *dbip,
+ void (*callback)(unsigned int, int), const char *name, const
int skip_first, struct solid *freesolid)
+{
+ struct display_list *gdlp;
+ struct display_list *next_gdlp;
+
+ gdlp = BU_LIST_NEXT(display_list, hdlp);
+ while (BU_LIST_NOT_HEAD(gdlp, hdlp)) {
+ char *dup_path;
+ char *tok;
+ int first = 1;
+ int found = 0;
+
+ next_gdlp = BU_LIST_PNEXT(display_list, gdlp);
+
+ dup_path = bu_strdup(bu_vls_addr(&gdlp->dl_path));
+ tok = strtok(dup_path, "/");
+ while (tok) {
+ if (first) {
+ first = 0;
+
+ if (skip_first) {
+ tok = strtok((char *)NULL, "/");
+ continue;
+ }
+ }
+
+ if (BU_STR_EQUAL(tok, name)) {
+ _dl_freeDisplayListItem(dbip, callback, gdlp, freesolid);
+ found = 1;
+
+ break;
+ }
+
+ tok = strtok((char *)NULL, "/");
+ }
+
+ /* Look for name in solids list */
+ if (!found) {
+ struct db_full_path subpath;
+
+ if (db_string_to_path(&subpath, dbip, name) == 0) {
+ eraseAllSubpathsFromSolidList(gdlp, &subpath, callback,
skip_first, freesolid);
+ db_free_full_path(&subpath);
+ }
+ }
+
+ bu_free((void *)dup_path, "dup_path");
+ gdlp = next_gdlp;
+ }
+}
+
+
+int
+_dl_eraseFirstSubpath(struct bu_list *hdlp, struct db_i *dbip,
+ void (*callback)(unsigned int, int),
+ struct display_list *gdlp,
+ struct db_full_path *subpath,
+ const int skip_first, struct solid *freesolid)
+{
+ struct solid *sp;
+ struct solid *nsp;
+ struct db_full_path dup_path;
+
+ db_full_path_init(&dup_path);
+
+ sp = BU_LIST_NEXT(solid, &gdlp->dl_headSolid);
+ while (BU_LIST_NOT_HEAD(sp, &gdlp->dl_headSolid)) {
+ nsp = BU_LIST_PNEXT(solid, sp);
+ if (db_full_path_subset(&sp->s_fullpath, subpath, skip_first)) {
+ int ret;
+ int full_len = sp->s_fullpath.fp_len;
+
+ if (callback != GED_FREE_VLIST_CALLBACK_PTR_NULL)
+ (*callback)(sp->s_dlist, 1);
+
+ sp->s_fullpath.fp_len = full_len - 1;
+ db_dup_full_path(&dup_path, &sp->s_fullpath);
+ sp->s_fullpath.fp_len = full_len;
+ BU_LIST_DEQUEUE(&sp->l);
+ FREE_SOLID(sp, &freesolid->l);
+
+ BU_LIST_DEQUEUE(&gdlp->l);
+
+ ret = headsolid_splitGDL(hdlp, dbip, gdlp, &dup_path);
+
+ db_free_full_path(&dup_path);
+
+ /* Free up the display list */
+ bu_vls_free(&gdlp->dl_path);
+ BU_FREE(gdlp, struct display_list);
+
+ return ret;
+ }
+ sp = nsp;
+ }
+
+ return 0;
+}
+
+
+/*
+ * Erase/remove display list item from headDisplay if path is a subset of
item's path.
+ */
+void
+_dl_eraseAllPathsFromDisplay(struct bu_list *hdlp, struct db_i *dbip,
+ void (*callback)(unsigned int, int),
+ const char *path,
+ const int skip_first,
+ struct solid *freesolid)
+{
+ struct display_list *gdlp;
+ struct display_list *next_gdlp;
+ struct db_full_path fullpath, subpath;
+
+ if (db_string_to_path(&subpath, dbip, path) == 0) {
+ gdlp = BU_LIST_NEXT(display_list, hdlp);
+ while (BU_LIST_NOT_HEAD(gdlp, hdlp)) {
+ gdlp->dl_wflag = 0;
+ gdlp = BU_LIST_PNEXT(display_list, gdlp);
+ }
+
+ gdlp = BU_LIST_NEXT(display_list, hdlp);
+ while (BU_LIST_NOT_HEAD(gdlp, hdlp)) {
+ next_gdlp = BU_LIST_PNEXT(display_list, gdlp);
+
+ /* This display list has already been visited. */
+ if (gdlp->dl_wflag) {
+ gdlp = next_gdlp;
+ continue;
+ }
+
+ /* Mark as being visited. */
+ gdlp->dl_wflag = 1;
+
+ if (db_string_to_path(&fullpath, dbip, bu_vls_addr(&gdlp->dl_path))
== 0) {
+ if (db_full_path_subset(&fullpath, &subpath, skip_first)) {
+ _dl_freeDisplayListItem(dbip, callback, gdlp, freesolid);
+ } else if (_dl_eraseFirstSubpath(hdlp, dbip, callback, gdlp,
&subpath, skip_first, freesolid)) {
+ gdlp = BU_LIST_NEXT(display_list, hdlp);
+ db_free_full_path(&fullpath);
+ continue;
+ }
+
+ db_free_full_path(&fullpath);
+ }
+
+ gdlp = next_gdlp;
+ }
+
+ db_free_full_path(&subpath);
+ }
+}
+
+
+void
+_dl_freeDisplayListItem (struct db_i *dbip,
+ void (*callback)(unsigned int, int),
+ struct display_list *gdlp, struct solid *freesolid)
+{
+ struct solid *sp;
+ struct directory *dp;
+
+ if (callback != GED_FREE_VLIST_CALLBACK_PTR_NULL) {
+
+ /* We can't assume the display lists are contiguous */
+ FOR_ALL_SOLIDS(sp, &gdlp->dl_headSolid) {
+ (*callback)(BU_LIST_FIRST(solid, &gdlp->dl_headSolid)->s_dlist, 1);
+ }
+ }
+
+ /* Free up the solids list associated with this display list */
+ while (BU_LIST_WHILE(sp, solid, &gdlp->dl_headSolid)) {
+ if (sp) {
+ dp = FIRST_SOLID(sp);
+ RT_CK_DIR(dp);
+ if (dp->d_addr == RT_DIR_PHONY_ADDR) {
+ (void)db_dirdelete(dbip, dp);
+ }
+
+ BU_LIST_DEQUEUE(&sp->l);
+ FREE_SOLID(sp, &freesolid->l);
+ }
+ }
+
+ /* Free up the display list */
+ BU_LIST_DEQUEUE(&gdlp->l);
+ bu_vls_free(&gdlp->dl_path);
+ BU_FREE(gdlp, struct display_list);
+}
+
+
+static void
+color_soltab(struct solid *sp)
+{
+ const struct mater *mp;
+
+ sp->s_cflag = 0;
+
+ /* the user specified the color, so use it */
+ if (sp->s_uflag) {
+ sp->s_color[0] = sp->s_basecolor[0];
+ sp->s_color[1] = sp->s_basecolor[1];
+ sp->s_color[2] = sp->s_basecolor[2];
+
+ return;
+ }
+
+ for (mp = rt_material_head(); mp != MATER_NULL; mp = mp->mt_forw) {
+ if (sp->s_regionid <= mp->mt_high &&
+ sp->s_regionid >= mp->mt_low) {
+ sp->s_color[0] = mp->mt_r;
+ sp->s_color[1] = mp->mt_g;
+ sp->s_color[2] = mp->mt_b;
+
+ return;
+ }
+ }
+
+ /*
+ * There is no region-id-based coloring entry in the
+ * table, so use the combination-record ("mater"
+ * command) based color if one was provided. Otherwise,
+ * use the default wireframe color.
+ * This is the "new way" of coloring things.
+ */
+
+ /* use wireframe_default_color */
+ if (sp->s_dflag)
+ sp->s_cflag = 1;
+
+ /* Be conservative and copy color anyway, to avoid black */
+ sp->s_color[0] = sp->s_basecolor[0];
+ sp->s_color[1] = sp->s_basecolor[1];
+ sp->s_color[2] = sp->s_basecolor[2];
+}
+
+
+/*
+ * Pass through the solid table and set pointer to appropriate
+ * mater structure.
+ */
+void
+dl_color_soltab(struct bu_list *hdlp)
+{
+ struct display_list *gdlp;
+ struct display_list *next_gdlp;
+ struct solid *sp;
+
+ gdlp = BU_LIST_NEXT(display_list, hdlp);
+ while (BU_LIST_NOT_HEAD(gdlp, hdlp)) {
+ next_gdlp = BU_LIST_PNEXT(display_list, gdlp);
+
+ FOR_ALL_SOLIDS(sp, &gdlp->dl_headSolid) {
+ color_soltab(sp);
+ }
+
+ gdlp = next_gdlp;
+ }
+}
+
+
+/* Set solid's basecolor, color, and color flags based on client data and tree
+ * * state. If user color isn't set in client data, the solid's region id
must be
+ * * set for proper material lookup.
+ * */
+static void
+solid_set_color_info(
+ struct solid *sp,
+ unsigned char *wireframe_color_override,
+ struct db_tree_state *tsp)
+{
+ unsigned char bcolor[3] = {255, 0, 0}; /* default */
+
+ sp->s_uflag = 0;
+ sp->s_dflag = 0;
+ if (wireframe_color_override) {
+ sp->s_uflag = 1;
+
+ bcolor[RED] = wireframe_color_override[RED];
+ bcolor[GRN] = wireframe_color_override[GRN];
+ bcolor[BLU] = wireframe_color_override[BLU];
+ } else if (tsp) {
+ if (tsp->ts_mater.ma_color_valid) {
+ bcolor[RED] = tsp->ts_mater.ma_color[RED] * 255.0;
+ bcolor[GRN] = tsp->ts_mater.ma_color[GRN] * 255.0;
+ bcolor[BLU] = tsp->ts_mater.ma_color[BLU] * 255.0;
+ } else {
+ sp->s_dflag = 1;
+ }
+ }
+
+ sp->s_basecolor[RED] = bcolor[RED];
+ sp->s_basecolor[GRN] = bcolor[GRN];
+ sp->s_basecolor[BLU] = bcolor[BLU];
+
+ color_soltab(sp);
+}
+
+/**
+ * * Compute the min, max, and center points of the solid.
+ * */
+static void
+bound_solid(struct solid *sp)
+{
+ point_t bmin, bmax;
+ int cmd;
+ VSET(bmin, INFINITY, INFINITY, INFINITY);
+ VSET(bmax, -INFINITY, -INFINITY, -INFINITY);
+ cmd = bn_vlist_bbox(&sp->s_vlist, &bmin, &bmax, NULL);
+ if (cmd) {
+ bu_log("unknown vlist op %d\n", cmd);
+ }
+ sp->s_center[X] = (bmin[X] + bmax[X]) * 0.5;
+ sp->s_center[Y] = (bmin[Y] + bmax[Y]) * 0.5;
+ sp->s_center[Z] = (bmin[Z] + bmax[Z]) * 0.5;
+
+ sp->s_size = bmax[X] - bmin[X];
+ V_MAX(sp->s_size, bmax[Y] - bmin[Y]);
+ V_MAX(sp->s_size, bmax[Z] - bmin[Z]);
+}
+
+
+static void
+solid_append_vlist(struct solid *sp, struct bn_vlist *vlist)
+{
+ if (BU_LIST_IS_EMPTY(&(sp->s_vlist))) {
+ sp->s_vlen = 0;
+ }
+
+ sp->s_vlen += bn_vlist_cmd_cnt(vlist);
+ BU_LIST_APPEND_LIST(&(sp->s_vlist), &(vlist->l));
+}
+
+void
+dl_add_path(struct display_list *gdlp, int dashflag, fastf_t transparency, int
dmode, int hiddenLine, struct bu_list *vhead, const struct db_full_path *pathp,
struct db_tree_state *tsp, unsigned char *wireframe_color_override, void
(*callback)(struct solid *sp), struct solid *freesolid)
+{
+ struct solid *sp;
+ GET_SOLID(sp, &freesolid->l);
+
+ solid_append_vlist(sp, (struct bn_vlist *)vhead);
+
+ bound_solid(sp);
+
+ db_dup_full_path(&sp->s_fullpath, pathp);
+
+ sp->s_flag = DOWN;
+ sp->s_iflag = DOWN;
+ sp->s_soldash = dashflag;
+ sp->s_Eflag = 0;
+
+ if (tsp) {
+ sp->s_regionid = tsp->ts_regionid;
+ }
+
+ solid_set_color_info(sp, wireframe_color_override, tsp);
+
+ sp->s_dlist = 0;
+ sp->s_transparency = transparency;
+ sp->s_dmode = dmode;
+ sp->s_hiddenLine = hiddenLine;
+
+ /* append solid to display list */
+ bu_semaphore_acquire(RT_SEM_MODEL);
+ BU_LIST_APPEND(gdlp->dl_headSolid.back, &sp->l);
+ bu_semaphore_release(RT_SEM_MODEL);
+
+ if (callback != GED_CREATE_VLIST_SOLID_CALLBACK_PTR_NULL) {
+ (*callback)(sp);
+ }
+
+}
+
+
+
+static fastf_t
+view_avg_size(struct bview *gvp)
+{
+ fastf_t view_aspect, x_size, y_size;
+
+ view_aspect = (fastf_t)gvp->gv_x_samples / gvp->gv_y_samples;
+ x_size = gvp->gv_size;
+ y_size = x_size / view_aspect;
+
+ return (x_size + y_size) / 2.0;
+}
+
+static fastf_t
+view_avg_sample_spacing(struct bview *gvp)
+{
+ fastf_t avg_view_size, avg_view_samples;
+
+ avg_view_size = view_avg_size(gvp);
+ avg_view_samples = (gvp->gv_x_samples + gvp->gv_y_samples) / 2.0;
+
+ return avg_view_size / avg_view_samples;
+}
+
+static fastf_t
+solid_point_spacing(struct bview *gvp, fastf_t solid_width)
+{
+ fastf_t radius, avg_view_size, avg_sample_spacing;
+ point2d_t p1, p2;
+
+ if (solid_width < SQRT_SMALL_FASTF)
+ solid_width = SQRT_SMALL_FASTF;
+
+ avg_view_size = view_avg_size(gvp);
+
+ /* Now, for the sake of simplicity we're going to make
+ * several assumptions:
+ * - our samples represent a grid of square pixels
+ * - a circle with a diameter half the width of the solid is a
+ * good proxy for the kind of curve that will be plotted
+ */
+ radius = solid_width / 4.0;
+ if (avg_view_size < solid_width) {
+ /* If the solid is larger than the view, it is
+ * probably only partly visible and likely isn't the
+ * primary focus of the user. We'll cap the point
+ * spacing and avoid wasting effort.
+ */
+ radius = avg_view_size / 4.0;
+ }
+
+ /* We imagine our representative circular curve lying in
+ * the XY plane centered at the origin.
+ *
+ * Suppose we're viewing the circle head on, and that the
+ * apex of the curve (0, radius) lies just inside the
+ * top edge of a pixel. Here we place a plotted point p1.
+ *
+ * As we continue clockwise around the circle we pass
+ * through neighboring pixels in the same row, until we
+ * vertically drop a distance equal to the pixel spacing,
+ * in which case we just barely enter a pixel in the next
+ * row. Here we place a plotted point p2 (y = radius -
+ * avg_sample_spacing).
+ *
+ * In theory, the line segment between p1 and p2 passes
+ * through all the same pixels that the actual curve does,
+ * and thus produces the exact same rasterization as if
+ * the curve between p1 and p2 was approximated with an
+ * infinite number of line segments.
+ *
+ * We assume that the distance between p1 and p2 is the
+ * maximum point sampling distance we can use for the
+ * curve which will give a perfect rasterization, i.e.
+ * the same rasterization as if we chose a point distance
+ * of 0.
+ */
+ p1[Y] = radius;
+ p1[X] = 0.0;
+
+ avg_sample_spacing = view_avg_sample_spacing(gvp);
+ if (avg_sample_spacing < radius) {
+ p2[Y] = radius - (avg_sample_spacing);
+ } else {
+ /* no particular reason other than symmetry, just need
+ * to prevent sqrt(negative).
+ */
+ p2[Y] = radius;
+ }
+ p2[X] = sqrt((radius * radius) - (p2[Y] * p2[Y]));
+
+ return DIST_PNT2_PNT2(p1, p2);
+}
+
+
+/* Choose a point spacing for the given solid (sp, ip) s.t. solid
+ * curves plotted with that spacing will look smooth when rasterized
+ * in the given view (gvp).
+ *
+ * TODO: view_avg_sample_spacing() might be sufficient if we can
+ * develop a general decimation routine for the resulting plots, in
+ * which case, this function could be removed.
+ */
+static fastf_t
+solid_point_spacing_for_view(
+ struct solid *sp,
+ struct rt_db_internal *ip,
+ struct bview *gvp)
+{
+ fastf_t point_spacing = 0.0;
+
+ if (ip->idb_major_type == DB5_MAJORTYPE_BRLCAD) {
+ switch (ip->idb_minor_type) {
+ case DB5_MINORTYPE_BRLCAD_TGC: {
+ struct rt_tgc_internal *tgc;
+ fastf_t avg_diameter;
+ fastf_t tgc_mag_a, tgc_mag_b, tgc_mag_c, tgc_mag_d;
+
+ RT_CK_DB_INTERNAL(ip);
+ tgc = (struct rt_tgc_internal *)ip->idb_ptr;
+ RT_TGC_CK_MAGIC(tgc);
+
+ tgc_mag_a = MAGNITUDE(tgc->a);
+ tgc_mag_b = MAGNITUDE(tgc->b);
+ tgc_mag_c = MAGNITUDE(tgc->c);
+ tgc_mag_d = MAGNITUDE(tgc->d);
+
+ avg_diameter = tgc_mag_a + tgc_mag_b + tgc_mag_c + tgc_mag_d;
+ avg_diameter /= 2.0;
+ point_spacing = solid_point_spacing(gvp, avg_diameter);
+ }
+ break;
+ case DB5_MINORTYPE_BRLCAD_BOT:
+ point_spacing = view_avg_sample_spacing(gvp);
+ break;
+ case DB5_MINORTYPE_BRLCAD_BREP: {
+ struct rt_brep_internal *bi;
+
+ RT_CK_DB_INTERNAL(ip);
+ bi = (struct rt_brep_internal *)ip->idb_ptr;
+ RT_BREP_CK_MAGIC(bi);
+
+ point_spacing = solid_point_spacing(gvp,
+ brep_est_avg_curve_len(bi) * M_2_PI * 2.0);
+ }
+ break;
+ default:
+ point_spacing = solid_point_spacing(gvp, sp->s_size);
+ }
+ } else {
+ point_spacing = solid_point_spacing(gvp, sp->s_size);
+ }
+
+ return point_spacing;
+}
+
+
+static fastf_t
+draw_solid_wireframe(struct solid *sp, struct db_i *dbip, struct db_tree_state
*tsp, struct bview *gvp)
+{
+ int ret;
+ struct bu_list vhead;
+ struct rt_db_internal dbintern;
+ struct rt_db_internal *ip = &dbintern;
+ struct rt_view_info info;
+
+ BU_LIST_INIT(&vhead);
+
+ ret = rt_db_get_internal(ip, DB_FULL_PATH_CUR_DIR(&sp->s_fullpath),
+ dbip, sp->s_mat, &rt_uniresource);
+
+ if (ret < 0) {
+ return -1;
+ }
+
+ if (gvp && gvp->gv_adaptive_plot && ip->idb_meth->ft_adaptive_plot) {
+
+ info.vhead = &vhead;
+ info.tol = tsp->ts_tol;
+ info.bot_threshold = (gvp) ? gvp->gv_bot_threshold : 0;
+
+ info.point_spacing = solid_point_spacing_for_view(sp, ip, gvp);
+
+ info.curve_spacing = sp->s_size / 2.0;
+
+ info.point_spacing /= gvp->gv_point_scale;
+ info.curve_spacing /= gvp->gv_curve_scale;
+
+ ret = ip->idb_meth->ft_adaptive_plot(ip, &info);
+ } else if (ip->idb_meth->ft_plot) {
+ info.bot_threshold = (gvp) ? gvp->gv_bot_threshold : 0;
+ ret = ip->idb_meth->ft_plot(&vhead, ip, tsp->ts_ttol,
+ tsp->ts_tol, &info);
+ }
+
+ rt_db_free_internal(ip);
+
+ if (ret < 0) {
+ bu_log("%s: plot failure\n",
DB_FULL_PATH_CUR_DIR(&sp->s_fullpath)->d_namep);
+
+ return -1;
+ }
+
+ /* add plot to solid */
+ solid_append_vlist(sp, (struct bn_vlist *)&vhead);
+
+ return 0;
+}
+
+
+int
+redraw_solid(struct solid *sp, struct db_i *dbip, struct db_tree_state *tsp,
struct bview *gvp)
+{
+ if (sp->s_dmode == _GED_WIREFRAME) {
+ /* replot wireframe */
+ if (BU_LIST_NON_EMPTY(&sp->s_vlist)) {
+ RT_FREE_VLIST(&sp->s_vlist);
+ }
+ return draw_solid_wireframe(sp, dbip, tsp, gvp);
+ }
+ return 0;
+}
+
+
+int
+dl_redraw(struct display_list *gdlp, struct db_i *dbip, struct db_tree_state
*tsp, struct bview *gvp, void (*callback)(struct display_list *), int
skip_subtractions)
+{
+ int ret = 0;
+ struct solid *sp;
+ for (BU_LIST_FOR(sp, solid, &gdlp->dl_headSolid)) {
+ if (!skip_subtractions || (skip_subtractions && !sp->s_soldash)) {
+ ret += redraw_solid(sp, dbip, tsp, gvp);
+ }
+ }
+ if (callback != GED_CREATE_VLIST_CALLBACK_PTR_NULL)
+ (*callback)(gdlp);
+ return ret;
+}
+
+union tree *
+append_solid_to_display_list(
+ struct db_tree_state *tsp,
+ const struct db_full_path *pathp,
+ struct rt_db_internal *ip,
+ void *client_data)
+{
+ point_t min, max;
+ struct solid *sp;
+ union tree *curtree;
+ struct bview_client_data *bview_data = (struct bview_client_data
*)client_data;
+
+ RT_CK_DB_INTERNAL(ip);
+ BG_CK_TESS_TOL(tsp->ts_ttol);
+ BN_CK_TOL(tsp->ts_tol);
+ RT_CK_RESOURCE(tsp->ts_resp);
+
+ VSETALL(min, INFINITY);
+ VSETALL(max, -INFINITY);
+
+ if (!bview_data) {
+ return TREE_NULL;
+ }
+
+ if (RT_G_DEBUG & RT_DEBUG_TREEWALK) {
+ char *sofar = db_path_to_string(pathp);
+
+ bu_log("append_solid_to_display_list(%s) path='%s'\n",
ip->idb_meth->ft_name, sofar);
+
+ bu_free((void *)sofar, "path string");
+ }
+
+ /* create solid */
+ GET_SOLID(sp, &(((struct solid *)bview_data->freesolid)->l));
+
+ sp->s_size = 0;
+ VSETALL(sp->s_center, 0.0);
+
+ if (ip->idb_meth->ft_bbox) {
+ if (ip->idb_meth->ft_bbox(ip, &min, &max, tsp->ts_tol) < 0) {
+ bu_log("%s: plot failure\n", DB_FULL_PATH_CUR_DIR(pathp)->d_namep);
+
+ return TREE_NULL;
+ }
+
+ sp->s_center[X] = (min[X] + max[X]) * 0.5;
+ sp->s_center[Y] = (min[Y] + max[Y]) * 0.5;
+ sp->s_center[Z] = (min[Z] + max[Z]) * 0.5;
+
+ sp->s_size = max[X] - min[X];
+ V_MAX(sp->s_size, max[Y] - min[Y]);
+ V_MAX(sp->s_size, max[Z] - min[Z]);
+ } else if (ip->idb_meth->ft_plot) {
+ /* As a fallback for primitives that don't have a bbox function, use
+ * the old bounding method of calculating a plot for the primitive and
+ * using the extent of the plotted segments as the bounds.
+ */
+ int plot_status;
+ struct bu_list vhead;
+ struct bn_vlist *vp;
+
+ BU_LIST_INIT(&vhead);
+
+ plot_status = ip->idb_meth->ft_plot(&vhead, ip, tsp->ts_ttol,
+ tsp->ts_tol, NULL);
+
+ if (plot_status < 0) {
+ bu_log("%s: plot failure\n", DB_FULL_PATH_CUR_DIR(pathp)->d_namep);
+
+ return TREE_NULL;
+ }
+
+ solid_append_vlist(sp, (struct bn_vlist *)&vhead);
+
+ bound_solid(sp);
+
+ while (BU_LIST_WHILE(vp, bn_vlist, &(sp->s_vlist))) {
+ BU_LIST_DEQUEUE(&vp->l);
+ bu_free(vp, "solid vp");
+ }
+ }
+
+ sp->s_vlen = 0;
+ db_dup_full_path(&sp->s_fullpath, pathp);
+ sp->s_flag = DOWN;
+ sp->s_iflag = DOWN;
+
+ if (bview_data->draw_solid_lines_only) {
+ sp->s_soldash = 0;
+ } else {
+ sp->s_soldash = (tsp->ts_sofar & (TS_SOFAR_MINUS|TS_SOFAR_INTER));
+ }
+
+ sp->s_Eflag = 0;
+ sp->s_regionid = tsp->ts_regionid;
+
+ if (ip->idb_type == ID_GRIP) {
+ float mater_color[3];
+
+ /* Temporarily change mater color for pseudo solid to get the desired
+ * default color.
+ */
+ mater_color[RED] = tsp->ts_mater.ma_color[RED];
+ mater_color[GRN] = tsp->ts_mater.ma_color[GRN];
+ mater_color[BLU] = tsp->ts_mater.ma_color[BLU];
+
+ tsp->ts_mater.ma_color[RED] = 0;
+ tsp->ts_mater.ma_color[GRN] = 128;
+ tsp->ts_mater.ma_color[BLU] = 128;
+
+ if (bview_data->wireframe_color_override) {
+ solid_set_color_info(sp, (unsigned char
*)&(bview_data->wireframe_color), tsp);
+ } else {
+ solid_set_color_info(sp, NULL, tsp);
+ }
+
+ tsp->ts_mater.ma_color[RED] = mater_color[RED];
+ tsp->ts_mater.ma_color[GRN] = mater_color[GRN];
+ tsp->ts_mater.ma_color[BLU] = mater_color[BLU];
+
+ } else {
+ if (bview_data->wireframe_color_override) {
+ unsigned char wire_color[3];
+ wire_color[RED] = (unsigned char)bview_data->wireframe_color[RED];
+ wire_color[GRN] = (unsigned char)bview_data->wireframe_color[GRN];
+ wire_color[BLU] = (unsigned char)bview_data->wireframe_color[BLU];
+ solid_set_color_info(sp, wire_color, tsp);
+ } else {
+ const char *attr_color = bu_avs_get(&ip->idb_avs,
db5_standard_attribute(ATTR_COLOR));
+ if (attr_color) {
+ int i;
+ unsigned char obj_color[3];
+ int color[3];
+ int color_cnt = sscanf(attr_color, "%3i%*c%3i%*c%3i", color+0,
color+1, color+2);
+ if (color_cnt == 3 && color[0] >= 0 && color[1] >= 0 &&
color[2] >= 0) {
+ for (i = 0; i < 3; i++) {
+ if (color[i] > 255) color[i] = 255;
+ }
+ obj_color[RED] = (unsigned char)color[RED];
+ obj_color[GRN] = (unsigned char)color[GRN];
+ obj_color[BLU] = (unsigned char)color[BLU];
+ solid_set_color_info(sp, obj_color, tsp);
+ } else {
+ solid_set_color_info(sp, NULL, tsp);
+ }
+ } else {
+ solid_set_color_info(sp, NULL, tsp);
+ }
+ }
+ }
+
+ sp->s_dlist = 0;
+ sp->s_transparency = bview_data->transparency;
+ sp->s_dmode = bview_data->dmode;
+ sp->s_hiddenLine = bview_data->hiddenLine;
+ MAT_COPY(sp->s_mat, tsp->ts_mat);
+
+ /* append solid to display list */
+ bu_semaphore_acquire(RT_SEM_MODEL);
+ BU_LIST_APPEND(bview_data->gdlp->dl_headSolid.back, &sp->l);
+ bu_semaphore_release(RT_SEM_MODEL);
+
+ /* indicate success by returning something other than TREE_NULL */
+ BU_GET(curtree, union tree);
+ RT_TREE_INIT(curtree);
+ curtree->tr_op = OP_NOP;
+
+ return curtree;
+}
+
+static void
+solid_copy_vlist(struct solid *sp, struct bn_vlist *vlist)
+{
+ BU_LIST_INIT(&(sp->s_vlist));
+ rt_vlist_copy(&(sp->s_vlist), (struct bu_list *)vlist);
+ sp->s_vlen = bn_vlist_cmd_cnt((struct bn_vlist *)(&(sp->s_vlist)));
+}
+
+int invent_solid(struct bu_list *hdlp, struct db_i *dbip,
+ void (*callback_create)(struct solid *), void
(*callback_free)(unsigned int, int),
+ char *name, struct bu_list *vhead, long int rgb, int copy,
fastf_t transparency, int dmode,
+ struct solid *freesolid, int csoltab)
+{
+ struct directory *dp;
+ struct solid *sp;
+ struct display_list *gdlp;
+ unsigned char type='0';
+
+ if (dbip == DBI_NULL)
+ return 0;
+
+ if ((dp = db_lookup(dbip, name, LOOKUP_QUIET)) != RT_DIR_NULL) {
+ if (dp->d_addr != RT_DIR_PHONY_ADDR) {
+ bu_log("invent_solid(%s) would clobber existing database entry,
ignored\n", name);
+ return -1;
+ }
+
+ /*
+ * Name exists from some other overlay,
+ * zap any associated solids
+ */
+ dl_erasePathFromDisplay(hdlp, dbip, callback_free, name, 0, freesolid);
+ }
+ /* Need to enter phony name in directory structure */
+ dp = db_diradd(dbip, name, RT_DIR_PHONY_ADDR, 0, RT_DIR_SOLID, (void
*)&type);
+
+ /* Obtain a fresh solid structure, and fill it in */
+ GET_SOLID(sp, &freesolid->l);
+
+ if (copy) {
+ solid_copy_vlist(sp, (struct bn_vlist *)vhead);
+ } else {
+ solid_append_vlist(sp, (struct bn_vlist *)vhead);
+ BU_LIST_INIT(vhead);
+ }
+ bound_solid(sp);
+
+ /* set path information -- this is a top level node */
+ db_add_node_to_full_path(&sp->s_fullpath, dp);
+
+ gdlp = dl_addToDisplay(hdlp, dbip, name);
+
+ sp->s_iflag = DOWN;
+ sp->s_soldash = 0;
+ sp->s_Eflag = 1; /* Can't be solid edited! */
+ sp->s_color[0] = sp->s_basecolor[0] = (rgb>>16) & 0xFF;
+ sp->s_color[1] = sp->s_basecolor[1] = (rgb>> 8) & 0xFF;
+ sp->s_color[2] = sp->s_basecolor[2] = (rgb) & 0xFF;
+ sp->s_regionid = 0;
+ sp->s_dlist = 0;
+
+ sp->s_uflag = 0;
+ sp->s_dflag = 0;
+ sp->s_cflag = 0;
+ sp->s_wflag = 0;
+
+ sp->s_transparency = transparency;
+ sp->s_dmode = dmode;
+
+ /* Solid successfully drawn, add to linked list of solid structs */
+ BU_LIST_APPEND(gdlp->dl_headSolid.back, &sp->l);
+
+ if (csoltab)
+ color_soltab(sp);
+
+ if (callback_create != GED_CREATE_VLIST_SOLID_CALLBACK_PTR_NULL)
+ (*callback_create)(sp);
+
+ return 0; /* OK */
+
+}
+
+int
+dl_set_illum(struct display_list *gdlp, const char *obj, int illum)
+{
+ int found = 0;
+ struct solid *sp;
+
+ FOR_ALL_SOLIDS(sp, &gdlp->dl_headSolid) {
+ size_t i;
+
+ for (i = 0; i < sp->s_fullpath.fp_len; ++i) {
+ if (*obj == *DB_FULL_PATH_GET(&sp->s_fullpath, i)->d_namep &&
+ BU_STR_EQUAL(obj, DB_FULL_PATH_GET(&sp->s_fullpath,
i)->d_namep)) {
+ found = 1;
+ if (illum)
+ sp->s_iflag = UP;
+ else
+ sp->s_iflag = DOWN;
+ }
+ }
+ }
+ return found;
+}
+
+void
+dl_set_iflag(struct bu_list *hdlp, int iflag)
+{
+ struct display_list *gdlp;
+ struct display_list *next_gdlp;
+ struct solid *sp;
+ /* calculate the bounding for of all solids being displayed */
+ gdlp = BU_LIST_NEXT(display_list, hdlp);
+ while (BU_LIST_NOT_HEAD(gdlp, hdlp)) {
+ next_gdlp = BU_LIST_PNEXT(display_list, gdlp);
+
+ FOR_ALL_SOLIDS(sp, &gdlp->dl_headSolid) {
+ sp->s_iflag = iflag;
+ }
+
+ gdlp = next_gdlp;
+ }
+}
+
+void
+dl_set_flag(struct bu_list *hdlp, int flag)
+{
+ struct display_list *gdlp;
+ struct display_list *next_gdlp;
+ struct solid *sp;
+ /* calculate the bounding for of all solids being displayed */
+ gdlp = BU_LIST_NEXT(display_list, hdlp);
+ while (BU_LIST_NOT_HEAD(gdlp, hdlp)) {
+ next_gdlp = BU_LIST_PNEXT(display_list, gdlp);
+
+ FOR_ALL_SOLIDS(sp, &gdlp->dl_headSolid) {
+ sp->s_flag = flag;
+ }
+
+ gdlp = next_gdlp;
+ }
+}
+
+void
+dl_set_wflag(struct bu_list *hdlp, int wflag)
+{
+ struct display_list *gdlp;
+ struct display_list *next_gdlp;
+ struct solid *sp;
+ /* calculate the bounding for of all solids being displayed */
+ gdlp = BU_LIST_NEXT(display_list, hdlp);
+ while (BU_LIST_NOT_HEAD(gdlp, hdlp)) {
+ next_gdlp = BU_LIST_PNEXT(display_list, gdlp);
+
+ FOR_ALL_SOLIDS(sp, &gdlp->dl_headSolid) {
+ sp->s_wflag = wflag;
+ }
+
+ gdlp = next_gdlp;
+ }
+}
+
+void
+dl_zap(struct bu_list *hdlp, struct db_i *dbip, void (*callback)(unsigned int,
int), struct solid *freesolid)
+{
+ struct solid *sp = SOLID_NULL;
+ struct display_list *gdlp = NULL;
+ struct bu_ptbl dls = BU_PTBL_INIT_ZERO;
+ struct directory *dp = RT_DIR_NULL;
+ size_t i = 0;
+
+ while (BU_LIST_WHILE(gdlp, display_list, hdlp)) {
+
+ if (callback != GED_FREE_VLIST_CALLBACK_PTR_NULL &&
BU_LIST_NON_EMPTY(&gdlp->dl_headSolid))
+ (*callback)(BU_LIST_FIRST(solid, &gdlp->dl_headSolid)->s_dlist,
+ BU_LIST_LAST(solid, &gdlp->dl_headSolid)->s_dlist -
+ BU_LIST_FIRST(solid, &gdlp->dl_headSolid)->s_dlist + 1);
+
+ while (BU_LIST_WHILE(sp, solid, &gdlp->dl_headSolid)) {
+ dp = FIRST_SOLID(sp);
+ RT_CK_DIR(dp);
+ if (dp->d_addr == RT_DIR_PHONY_ADDR) {
+ if (db_dirdelete(dbip, dp) < 0) {
+ bu_log("ged_zap: db_dirdelete failed\n");
+ }
+ }
+
+ BU_LIST_DEQUEUE(&sp->l);
+ FREE_SOLID(sp, &freesolid->l);
+ }
+
+ BU_LIST_DEQUEUE(&gdlp->l);
+ /* queue up for free */
+ bu_ptbl_ins_unique(&dls, (long *)gdlp);
+ gdlp = NULL;
+ }
+
+ /* Free all display lists */
+ for(i = 0; i < BU_PTBL_LEN(&dls); i++) {
+ gdlp = (struct display_list *)BU_PTBL_GET(&dls, i);
+ bu_vls_free(&gdlp->dl_path);
+ BU_FREE(gdlp, struct display_list);
+ }
+ bu_ptbl_free(&dls);
+}
+
+int
+dl_how(struct bu_list *hdlp, struct bu_vls *vls, struct directory **dpp, int
both)
+{
+ size_t i;
+ struct display_list *gdlp;
+ struct display_list *next_gdlp;
+ struct solid *sp;
+ struct directory **tmp_dpp;
+
+ gdlp = BU_LIST_NEXT(display_list, hdlp);
+ while (BU_LIST_NOT_HEAD(gdlp, hdlp)) {
+ next_gdlp = BU_LIST_PNEXT(display_list, gdlp);
+
+ FOR_ALL_SOLIDS(sp, &gdlp->dl_headSolid) {
+ for (i = 0, tmp_dpp = dpp;
+ i < sp->s_fullpath.fp_len && *tmp_dpp != RT_DIR_NULL;
+ ++i, ++tmp_dpp) {
+ if (sp->s_fullpath.fp_names[i] != *tmp_dpp)
+ break;
+ }
+
+ if (*tmp_dpp != RT_DIR_NULL)
+ continue;
+
+
+ /* found a match */
+ if (sp->s_hiddenLine) {
+ if (both)
+ bu_vls_printf(vls, "%d 1", _GED_HIDDEN_LINE);
+ else
+ bu_vls_printf(vls, "%d", _GED_HIDDEN_LINE);
+ } else {
+ if (both)
+ bu_vls_printf(vls, "%d %g", sp->s_dmode,
sp->s_transparency);
+ else
+ bu_vls_printf(vls, "%d", sp->s_dmode);
+ }
+
+ return 1;
+ }
+
+ gdlp = next_gdlp;
+ }
+
+ return 0;
+}
+
+
+void
+dl_plot(struct bu_list *hdlp, FILE *fp, mat_t model2view, int floating, mat_t
center, fastf_t scale, int Three_D, int Z_clip)
+{
+ struct display_list *gdlp;
+ struct display_list *next_gdlp;
+ struct solid *sp;
+ struct bn_vlist *vp;
+ static vect_t clipmin, clipmax;
+ static vect_t last; /* last drawn point */
+ static vect_t fin;
+ static vect_t start;
+ int Dashing; /* linetype is dashed */
+
+ if (floating) {
+ pd_3space(fp,
+ -center[MDX] - scale,
+ -center[MDY] - scale,
+ -center[MDZ] - scale,
+ -center[MDX] + scale,
+ -center[MDY] + scale,
+ -center[MDZ] + scale);
+ Dashing = 0;
+ pl_linmod(fp, "solid");
+
+ gdlp = BU_LIST_NEXT(display_list, hdlp);
+ while (BU_LIST_NOT_HEAD(gdlp, hdlp)) {
+ next_gdlp = BU_LIST_PNEXT(display_list, gdlp);
+
+ FOR_ALL_SOLIDS(sp, &gdlp->dl_headSolid) {
+ /* Could check for differences from last color */
+ pl_color(fp,
+ sp->s_color[0],
+ sp->s_color[1],
+ sp->s_color[2]);
+ if (Dashing != sp->s_soldash) {
+ if (sp->s_soldash)
+ pl_linmod(fp, "dotdashed");
+ else
+ pl_linmod(fp, "solid");
+ Dashing = sp->s_soldash;
+ }
+ bn_vlist_to_uplot(fp, &(sp->s_vlist));
+ }
+
+ gdlp = next_gdlp;
+ }
+
+ return;
+ }
+ /*
+ * Integer output version, either 2-D or 3-D.
+ * Viewing region is from -1.0 to +1.0
+ * which is mapped to integer space -2048 to +2048 for plotting.
+ * Compute the clipping bounds of the screen in view space.
+ */
+ clipmin[X] = -1.0;
+ clipmax[X] = 1.0;
+ clipmin[Y] = -1.0;
+ clipmax[Y] = 1.0;
+ if (Z_clip) {
+ clipmin[Z] = -1.0;
+ clipmax[Z] = 1.0;
+ } else {
+ clipmin[Z] = -1.0e20;
+ clipmax[Z] = 1.0e20;
+ }
+
+ if (Three_D)
+ pl_3space(fp, (int)DG_GED_MIN, (int)DG_GED_MIN, (int)DG_GED_MIN,
(int)DG_GED_MAX, (int)DG_GED_MAX, (int)DG_GED_MAX);
+ else
+ pl_space(fp, (int)DG_GED_MIN, (int)DG_GED_MIN, (int)DG_GED_MAX,
(int)DG_GED_MAX);
+ pl_erase(fp);
+ Dashing = 0;
+ pl_linmod(fp, "solid");
+
+ gdlp = BU_LIST_NEXT(display_list, hdlp);
+ while (BU_LIST_NOT_HEAD(gdlp, hdlp)) {
+ next_gdlp = BU_LIST_PNEXT(display_list, gdlp);
+
+ FOR_ALL_SOLIDS(sp, &gdlp->dl_headSolid) {
+ if (Dashing != sp->s_soldash) {
+ if (sp->s_soldash)
+ pl_linmod(fp, "dotdashed");
+ else
+ pl_linmod(fp, "solid");
+ Dashing = sp->s_soldash;
+ }
+ for (BU_LIST_FOR(vp, bn_vlist, &(sp->s_vlist))) {
+ int i;
+ int nused = vp->nused;
+ int *cmd = vp->cmd;
+ point_t *pt = vp->pt;
+ for (i = 0; i < nused; i++, cmd++, pt++) {
+ switch (*cmd) {
+ case BN_VLIST_POLY_START:
+ case BN_VLIST_POLY_VERTNORM:
+ case BN_VLIST_TRI_START:
+ case BN_VLIST_TRI_VERTNORM:
+ continue;
+ case BN_VLIST_POLY_MOVE:
+ case BN_VLIST_LINE_MOVE:
+ case BN_VLIST_TRI_MOVE:
+ /* Move, not draw */
+ MAT4X3PNT(last, model2view, *pt);
+ continue;
+ case BN_VLIST_LINE_DRAW:
+ case BN_VLIST_POLY_DRAW:
+ case BN_VLIST_POLY_END:
+ case BN_VLIST_TRI_DRAW:
+ case BN_VLIST_TRI_END:
+ /* draw */
+ MAT4X3PNT(fin, model2view, *pt);
+ VMOVE(start, last);
+ VMOVE(last, fin);
+ break;
+ }
+ if (bn_ray_vclip(start, fin, clipmin, clipmax) == 0)
+ continue;
+
+ if (Three_D) {
+ /* Could check for differences from last color */
+ pl_color(fp,
+ sp->s_color[0],
+ sp->s_color[1],
+ sp->s_color[2]);
+ pl_3line(fp,
+ (int)(start[X] * DG_GED_MAX),
+ (int)(start[Y] * DG_GED_MAX),
+ (int)(start[Z] * DG_GED_MAX),
+ (int)(fin[X] * DG_GED_MAX),
+ (int)(fin[Y] * DG_GED_MAX),
+ (int)(fin[Z] * DG_GED_MAX));
+ } else {
+ pl_line(fp,
+ (int)(start[0] * DG_GED_MAX),
+ (int)(start[1] * DG_GED_MAX),
+ (int)(fin[0] * DG_GED_MAX),
+ (int)(fin[1] * DG_GED_MAX));
+ }
+ }
+ }
+ }
+
+ gdlp = next_gdlp;
+ }
+}
+
+
+struct coord {
+ short x;
+ short y;
+};
+
+struct stroke {
+ struct coord pixel; /* starting scan, nib */
+ short xsign; /* 0 or +1 */
+ short ysign; /* -1, 0, or +1 */
+ int ymajor; /* true if Y is major dir. */
+ short major; /* major dir delta (nonneg) */
+ short minor; /* minor dir delta (nonneg) */
+ short e; /* DDA error accumulator */
+ short de; /* increment for `e' */
+};
+
+/*
+ * Method:
+ * Modified Bresenham algorithm. Guaranteed to mark a dot for
+ * a zero-length stroke.
+ */
+static void
+raster(unsigned char **image, struct stroke *vp, unsigned char *color, size_t
size)
+{
+ size_t dy; /* raster within active band */
+
+ /*
+ * Write the color of this vector on all pixels.
+ */
+ for (dy = vp->pixel.y; dy <= size;) {
+
+ /* set the appropriate pixel in the buffer to color */
+ image[size-dy][vp->pixel.x*3] = color[0];
+ image[size-dy][vp->pixel.x*3+1] = color[1];
+ image[size-dy][vp->pixel.x*3+2] = color[2];
+
+ if (vp->major-- == 0)
+ return; /* Done */
+
+ if (vp->e < 0) {
+ /* advance major & minor */
+ dy += vp->ysign;
+ vp->pixel.x += vp->xsign;
+ vp->e += vp->de;
+ } else {
+ /* advance major only */
+ if (vp->ymajor) /* Y is major dir */
+ ++dy;
+ else /* X is major dir */
+ vp->pixel.x += vp->xsign;
+ vp->e -= vp->minor;
+ }
+ }
+}
+
+static void
+draw_stroke(unsigned char **image, struct coord *coord1, struct coord *coord2,
unsigned char *color, size_t size)
+{
+ struct stroke cur_stroke;
+ struct stroke *vp = &cur_stroke;
+
+ /* arrange for pt1 to have the smaller Y-coordinate: */
+ if (coord1->y > coord2->y) {
+ struct coord *temp; /* temporary for swap */
+
+ temp = coord1; /* swap pointers */
+ coord1 = coord2;
+ coord2 = temp;
+ }
+
+ /* set up DDA parameters for stroke */
+ vp->pixel = *coord1; /* initial pixel */
+ vp->major = coord2->y - vp->pixel.y; /* always nonnegative */
+ vp->ysign = vp->major ? 1 : 0;
+ vp->minor = coord2->x - vp->pixel.x;
+ vp->xsign = vp->minor ? (vp->minor > 0 ? 1 : -1) : 0;
+ if (vp->xsign < 0)
+ vp->minor = -vp->minor;
+
+ /* if Y is not really major, correct the assignments */
+ vp->ymajor = vp->minor <= vp->major;
+ if (!vp->ymajor) {
+ short temp; /* temporary for swap */
+
+ temp = vp->minor;
+ vp->minor = vp->major;
+ vp->major = temp;
+ }
+
+ vp->e = vp->major / 2 - vp->minor; /* initial DDA error */
+ vp->de = vp->major - vp->minor;
+
+ raster(image, vp, color, size);
+}
+
+
+static void
+draw_png_solid(fastf_t perspective, unsigned char **image, struct solid *sp,
matp_t psmat, size_t size, size_t half_size)
+{
+ static vect_t last;
+ point_t clipmin = {-1.0, -1.0, -MAX_FASTF};
+ point_t clipmax = {1.0, 1.0, MAX_FASTF};
+ struct bn_vlist *tvp;
+ point_t *pt_prev=NULL;
+ fastf_t dist_prev=1.0;
+ fastf_t dist;
+ struct bn_vlist *vp = (struct bn_vlist *)&sp->s_vlist;
+ fastf_t delta;
+ struct coord coord1;
+ struct coord coord2;
+
+ /* delta is used in clipping to insure clipped endpoint is slightly
+ * in front of eye plane (perspective mode only).
+ * This value is a SWAG that seems to work OK.
+ */
+ delta = psmat[15]*0.0001;
+ if (delta < 0.0)
+ delta = -delta;
+ if (delta < SQRT_SMALL_FASTF)
+ delta = SQRT_SMALL_FASTF;
+
+ for (BU_LIST_FOR(tvp, bn_vlist, &vp->l)) {
+ int i;
+ int nused = tvp->nused;
+ int *cmd = tvp->cmd;
+ point_t *pt = tvp->pt;
+ for (i = 0; i < nused; i++, cmd++, pt++) {
+ static vect_t start, fin;
+ switch (*cmd) {
+ case BN_VLIST_POLY_START:
+ case BN_VLIST_POLY_VERTNORM:
+ case BN_VLIST_TRI_START:
+ case BN_VLIST_TRI_VERTNORM:
+ continue;
+ case BN_VLIST_POLY_MOVE:
+ case BN_VLIST_LINE_MOVE:
+ case BN_VLIST_TRI_MOVE:
+ /* Move, not draw */
+ if (perspective > 0) {
+ /* cannot apply perspective transformation to
+ * points behind eye plane!!!!
+ */
+ dist = VDOT(*pt, &psmat[12]) + psmat[15];
+ if (dist <= 0.0) {
+ pt_prev = pt;
+ dist_prev = dist;
+ continue;
+ } else {
+ MAT4X3PNT(last, psmat, *pt);
+ dist_prev = dist;
+ pt_prev = pt;
+ }
+ } else
+ MAT4X3PNT(last, psmat, *pt);
+ continue;
+ case BN_VLIST_POLY_DRAW:
+ case BN_VLIST_POLY_END:
+ case BN_VLIST_LINE_DRAW:
+ case BN_VLIST_TRI_DRAW:
+ case BN_VLIST_TRI_END:
+ /* draw */
+ if (perspective > 0) {
+ /* cannot apply perspective transformation to
+ * points behind eye plane!!!!
+ */
+ dist = VDOT(*pt, &psmat[12]) + psmat[15];
+ if (dist <= 0.0) {
+ if (dist_prev <= 0.0) {
+ /* nothing to plot */
+ dist_prev = dist;
+ pt_prev = pt;
+ continue;
+ } else {
+ if (pt_prev) {
+ fastf_t alpha;
+ vect_t diff;
+ point_t tmp_pt;
+
+ /* clip this end */
+ VSUB2(diff, *pt, *pt_prev);
+ alpha = (dist_prev - delta) / (dist_prev -
dist);
+ VJOIN1(tmp_pt, *pt_prev, alpha, diff);
+ MAT4X3PNT(fin, psmat, tmp_pt);
+ }
+ }
+ } else {
+ if (dist_prev <= 0.0) {
+ if (pt_prev) {
+ fastf_t alpha;
+ vect_t diff;
+ point_t tmp_pt;
+
+ /* clip other end */
+ VSUB2(diff, *pt, *pt_prev);
+ alpha = (-dist_prev + delta) / (dist -
dist_prev);
+ VJOIN1(tmp_pt, *pt_prev, alpha, diff);
+ MAT4X3PNT(last, psmat, tmp_pt);
+ MAT4X3PNT(fin, psmat, *pt);
+ }
+ } else {
+ MAT4X3PNT(fin, psmat, *pt);
+ }
+ }
+ } else
+ MAT4X3PNT(fin, psmat, *pt);
+ VMOVE(start, last);
+ VMOVE(last, fin);
+ break;
+ }
+
+ if (bn_ray_vclip(start, fin, clipmin, clipmax) == 0)
+ continue;
+
+ coord1.x = start[0] * half_size + half_size;
+ coord1.y = start[1] * half_size + half_size;
+ coord2.x = fin[0] * half_size + half_size;
+ coord2.y = fin[1] * half_size + half_size;
+ draw_stroke(image, &coord1, &coord2, sp->s_color, size);
+ }
+ }
+}
+
+
+void
+dl_png(struct bu_list *hdlp, mat_t model2view, fastf_t perspective, vect_t
eye_pos, size_t size, size_t half_size, unsigned char **image)
+{
+ struct display_list *gdlp;
+ struct display_list *next_gdlp;
+ mat_t newmat;
+ matp_t mat;
+ mat_t perspective_mat;
+ struct solid *sp;
+
+ mat = model2view;
+
+ if (0 < perspective) {
+ point_t l, h;
+
+ VSET(l, -1.0, -1.0, -1.0);
+ VSET(h, 1.0, 1.0, 200.0);
+
+ if (ZERO(eye_pos[Z] - 1.0)) {
+ /* This way works, with reasonable Z-clipping */
+ persp_mat(perspective_mat, perspective,
+ (fastf_t)1.0f, (fastf_t)0.01f, (fastf_t)1.0e10f,
(fastf_t)1.0f);
+ } else {
+ /* This way does not have reasonable Z-clipping,
+ * but includes shear, for GDurf's testing.
+ */
+ deering_persp_mat(perspective_mat, l, h, eye_pos);
+ }
+
+ bn_mat_mul(newmat, perspective_mat, mat);
+ mat = newmat;
+ }
+
+ gdlp = BU_LIST_NEXT(display_list, hdlp);
+ while (BU_LIST_NOT_HEAD(gdlp, hdlp)) {
+ next_gdlp = BU_LIST_PNEXT(display_list, gdlp);
+
+ FOR_ALL_SOLIDS(sp, &gdlp->dl_headSolid) {
+ draw_png_solid(perspective, image, sp, mat, size, half_size);
+ }
+
+ gdlp = next_gdlp;
+ }
+}
+
+
+static void
+ps_draw_header(FILE *fp, char *font, char *title, char *creator, int
linewidth, fastf_t scale, int xoffset, int yoffset)
+{
+ fprintf(fp, "%%!PS-Adobe-1.0\n\
+%%begin(plot)\n\
+%%%%DocumentFonts: %s\n",
+ font);
+
+ fprintf(fp, "%%%%Title: %s\n", title);
+
+ fprintf(fp, "\
+%%%%Creator: %s\n\
+%%%%BoundingBox: 0 0 324 324 %% 4.5in square, for TeX\n\
+%%%%EndComments\n\
+\n",
+ creator);
+
+ fprintf(fp, "\
+%d setlinewidth\n\
+\n", linewidth);
+
+ fprintf(fp, "\
+%% Sizes, made functions to avoid scaling if not needed\n\
+/FntH /%s findfont 80 scalefont def\n\
+/DFntL { /FntL /%s findfont 73.4 scalefont def } def\n\
+/DFntM { /FntM /%s findfont 50.2 scalefont def } def\n\
+/DFntS { /FntS /%s findfont 44 scalefont def } def\n\
+\n", font, font, font, font);
+
+ fprintf(fp, "\
+%% line styles\n\
+/NV { [] 0 setdash } def %% normal vectors\n\
+/DV { [8] 0 setdash } def %% dotted vectors\n\
+/DDV { [8 8 32 8] 0 setdash } def %% dot-dash vectors\n\
+/SDV { [32 8] 0 setdash } def %% short-dash vectors\n\
+/LDV { [64 8] 0 setdash } def %% long-dash vectors\n\
+\n\
+/NEWPG {\n\
+ %d %d translate\n\
+ %f %f scale %% 0-4096 to 324 units (4.5 inches)\n\
+} def\n\
+\n\
+FntH setfont\n\
+NEWPG\n\
+",
+ xoffset, yoffset, scale, scale);
+}
+
+static void
+ps_draw_solid(fastf_t perspective, FILE *fp, struct solid *sp, matp_t psmat)
+{
+ static vect_t last;
+ point_t clipmin = {-1.0, -1.0, -MAX_FASTF};
+ point_t clipmax = {1.0, 1.0, MAX_FASTF};
+ struct bn_vlist *tvp;
+ point_t *pt_prev=NULL;
+ fastf_t dist_prev=1.0;
+ fastf_t dist;
+ struct bn_vlist *vp = (struct bn_vlist *)&sp->s_vlist;
+ fastf_t delta;
+
+ fprintf(fp, "%f %f %f setrgbcolor\n",
+ PS_COLOR(sp->s_color[0]),
+ PS_COLOR(sp->s_color[1]),
+ PS_COLOR(sp->s_color[2]));
+
+ /* delta is used in clipping to insure clipped endpoint is slightly
+ * in front of eye plane (perspective mode only).
+ * This value is a SWAG that seems to work OK.
+ */
+ delta = psmat[15]*0.0001;
+ if (delta < 0.0)
+ delta = -delta;
+ if (delta < SQRT_SMALL_FASTF)
+ delta = SQRT_SMALL_FASTF;
+
+ for (BU_LIST_FOR(tvp, bn_vlist, &vp->l)) {
+ size_t i;
+ size_t nused = tvp->nused;
+ int *cmd = tvp->cmd;
+ point_t *pt = tvp->pt;
+ for (i = 0; i < nused; i++, cmd++, pt++) {
+ static vect_t start, fin;
+ switch (*cmd) {
+ case BN_VLIST_POLY_START:
+ case BN_VLIST_POLY_VERTNORM:
+ case BN_VLIST_TRI_START:
+ case BN_VLIST_TRI_VERTNORM:
+ continue;
+ case BN_VLIST_POLY_MOVE:
+ case BN_VLIST_LINE_MOVE:
+ case BN_VLIST_TRI_MOVE:
+ /* Move, not draw */
+ if (perspective > 0) {
+ /* cannot apply perspective transformation to
+ * points behind eye plane!!!!
+ */
+ dist = VDOT(*pt, &psmat[12]) + psmat[15];
+ if (dist <= 0.0) {
+ pt_prev = pt;
+ dist_prev = dist;
+ continue;
+ } else {
+ MAT4X3PNT(last, psmat, *pt);
+ dist_prev = dist;
+ pt_prev = pt;
+ }
+ } else
+ MAT4X3PNT(last, psmat, *pt);
+ continue;
+ case BN_VLIST_POLY_DRAW:
+ case BN_VLIST_POLY_END:
+ case BN_VLIST_LINE_DRAW:
+ case BN_VLIST_TRI_DRAW:
+ case BN_VLIST_TRI_END:
+ /* draw */
+ if (perspective > 0) {
+ /* cannot apply perspective transformation to
+ * points behind eye plane!!!!
+ */
+ dist = VDOT(*pt, &psmat[12]) + psmat[15];
+ if (dist <= 0.0) {
+ if (dist_prev <= 0.0) {
+ /* nothing to plot */
+ dist_prev = dist;
+ pt_prev = pt;
+ continue;
+ } else {
+ if (pt_prev) {
+ fastf_t alpha;
+ vect_t diff;
+ point_t tmp_pt;
+
+ /* clip this end */
+ VSUB2(diff, *pt, *pt_prev);
+ alpha = (dist_prev - delta) / (dist_prev -
dist);
+ VJOIN1(tmp_pt, *pt_prev, alpha, diff);
+ MAT4X3PNT(fin, psmat, tmp_pt);
+ }
+ }
+ } else {
+ if (dist_prev <= 0.0) {
+ if (pt_prev) {
+ fastf_t alpha;
+ vect_t diff;
+ point_t tmp_pt;
+
+ /* clip other end */
+ VSUB2(diff, *pt, *pt_prev);
+ alpha = (-dist_prev + delta) / (dist -
dist_prev);
+ VJOIN1(tmp_pt, *pt_prev, alpha, diff);
+ MAT4X3PNT(last, psmat, tmp_pt);
+ MAT4X3PNT(fin, psmat, *pt);
+ }
+ } else {
+ MAT4X3PNT(fin, psmat, *pt);
+ }
+ }
+ } else
+ MAT4X3PNT(fin, psmat, *pt);
+ VMOVE(start, last);
+ VMOVE(last, fin);
+ break;
+ }
+
+ if (bn_ray_vclip(start, fin, clipmin, clipmax) == 0)
+ continue;
+
+ fprintf(fp,
+ "newpath %d %d moveto %d %d lineto stroke\n",
+ PS_COORD(start[0] * 2047),
+ PS_COORD(start[1] * 2047),
+ PS_COORD(fin[0] * 2047),
+ PS_COORD(fin[1] * 2047));
+ }
+ }
+}
+
+static void
+ps_draw_body(struct bu_list *hdlp, FILE *fp, mat_t model2view, fastf_t
perspective, vect_t eye_pos)
+{
+ struct display_list *gdlp;
+ struct display_list *next_gdlp;
+ mat_t newmat;
+ matp_t mat;
+ mat_t perspective_mat;
+ struct solid *sp;
+
+ mat = model2view;
+
+ if (0 < perspective) {
+ point_t l, h;
+
+ VSET(l, -1.0, -1.0, -1.0);
+ VSET(h, 1.0, 1.0, 200.0);
+
+ if (ZERO(eye_pos[Z] - 1.0)) {
+ /* This way works, with reasonable Z-clipping */
+ persp_mat(perspective_mat, perspective,
+ (fastf_t)1.0f, (fastf_t)0.01f, (fastf_t)1.0e10f,
(fastf_t)1.0f);
+ } else {
+ /* This way does not have reasonable Z-clipping,
+ * but includes shear, for GDurf's testing.
+ */
+ deering_persp_mat(perspective_mat, l, h, eye_pos);
+ }
+
+ bn_mat_mul(newmat, perspective_mat, mat);
+ mat = newmat;
+ }
+
+ gdlp = BU_LIST_NEXT(display_list, hdlp);
+ while (BU_LIST_NOT_HEAD(gdlp, hdlp)) {
+ next_gdlp = BU_LIST_PNEXT(display_list, gdlp);
+
+ FOR_ALL_SOLIDS(sp, &gdlp->dl_headSolid) {
+ ps_draw_solid(perspective, fp, sp, mat);
+ }
+
+ gdlp = next_gdlp;
+ }
+}
+
+
+static void
+ps_draw_border(FILE *fp, float red, float green, float blue)
+{
+ fprintf(fp, "%f %f %f setrgbcolor\n", red, green, blue);
+ fprintf(fp, "newpath 0 0 moveto 4096 0 lineto stroke\n");
+ fprintf(fp, "newpath 4096 0 moveto 4096 4096 lineto stroke\n");
+ fprintf(fp, "newpath 4096 4096 moveto 0 4096 lineto stroke\n");
+ fprintf(fp, "newpath 0 4096 moveto 0 0 lineto stroke\n");
+}
+
+
+static void
+ps_draw_footer(FILE *fp)
+{
+ fputs("% showpage % uncomment to use raw file\n", fp);
+ fputs("%end(plot)\n", fp);
+}
+
+void
+dl_ps(struct bu_list *hdlp, FILE *fp, int border, char *font, char *title,
char *creator, int linewidth, fastf_t scale, int xoffset, int yoffset, mat_t
model2view, fastf_t perspective, vect_t eye_pos, float red, float green, float
blue)
+{
+ ps_draw_header(fp, font, title, creator, linewidth, scale, xoffset,
yoffset);
+ if (border)
+ ps_draw_border(fp, red, green, blue);
+ ps_draw_body(hdlp, fp, model2view, perspective, eye_pos);
+ ps_draw_footer(fp);
+
+}
+
+
+void
+dl_print_schain(struct bu_list *hdlp, struct db_i *dbip, int lvl, int vlcmds,
struct bu_vls *vls)
+{
+ struct display_list *gdlp;
+ struct display_list *next_gdlp;
+ struct solid *sp;
+ struct bn_vlist *vp;
+
+ if (!vlcmds) {
+ /*
+ * Given a pointer to a member of the circularly linked list of solids
+ * (typically the head), chase the list and print out the information
+ * about each solid structure.
+ */
+ size_t nvlist;
+ size_t npts;
+
+ if (dbip == DBI_NULL) return;
+
+ gdlp = BU_LIST_NEXT(display_list, hdlp);
+ while (BU_LIST_NOT_HEAD(gdlp, hdlp)) {
+ next_gdlp = BU_LIST_PNEXT(display_list, gdlp);
+
+ FOR_ALL_SOLIDS(sp, &gdlp->dl_headSolid) {
+ if (lvl <= -2) {
+ /* print only leaves */
+ bu_vls_printf(vls, "%s ", LAST_SOLID(sp)->d_namep);
+ continue;
+ }
+
+ db_path_to_vls(vls, &sp->s_fullpath);
+
+ if ((lvl != -1) && (sp->s_iflag == UP))
+ bu_vls_printf(vls, " ILLUM");
+
+ bu_vls_printf(vls, "\n");
+
+ if (lvl <= 0)
+ continue;
+
+ /* convert to the local unit for printing */
+ bu_vls_printf(vls, " cent=(%.3f, %.3f, %.3f) sz=%g ",
+ sp->s_center[X]*dbip->dbi_base2local,
+ sp->s_center[Y]*dbip->dbi_base2local,
+ sp->s_center[Z]*dbip->dbi_base2local,
+ sp->s_size*dbip->dbi_base2local);
+ bu_vls_printf(vls, "reg=%d\n", sp->s_regionid);
+ bu_vls_printf(vls, " basecolor=(%d, %d, %d) color=(%d, %d,
%d)%s%s%s\n",
+ sp->s_basecolor[0],
+ sp->s_basecolor[1],
+ sp->s_basecolor[2],
+ sp->s_color[0],
+ sp->s_color[1],
+ sp->s_color[2],
+ sp->s_uflag?" U":"",
+ sp->s_dflag?" D":"",
+ sp->s_cflag?" C":"");
+
+ if (lvl <= 1)
+ continue;
+
+ /* Print the actual vector list */
+ nvlist = 0;
+ npts = 0;
+ for (BU_LIST_FOR(vp, bn_vlist, &(sp->s_vlist))) {
+ int i;
+ int nused = vp->nused;
+ int *cmd = vp->cmd;
+ point_t *pt = vp->pt;
+
+ BN_CK_VLIST(vp);
+ nvlist++;
+ npts += nused;
+
+ if (lvl <= 2)
+ continue;
+
+ for (i = 0; i < nused; i++, cmd++, pt++) {
+ bu_vls_printf(vls, " %s (%g, %g, %g)\n",
+ bn_vlist_get_cmd_description(*cmd),
+ V3ARGS(*pt));
+ }
+ }
+
+ bu_vls_printf(vls, " %zu vlist structures, %zu pts\n", nvlist,
npts);
+ bu_vls_printf(vls, " %zu pts (via bn_ck_vlist)\n",
bn_ck_vlist(&(sp->s_vlist)));
+ }
+
+ gdlp = next_gdlp;
+ }
+
+ } else {
+ /*
+ * Given a pointer to a member of the circularly linked list of solids
+ * (typically the head), chase the list and print out the vlist cmds
+ * for each structure.
+ */
+
+ if (dbip == DBI_NULL) return;
+
+ gdlp = BU_LIST_NEXT(display_list, hdlp);
+ while (BU_LIST_NOT_HEAD(gdlp, hdlp)) {
+ next_gdlp = BU_LIST_PNEXT(display_list, gdlp);
+
+ FOR_ALL_SOLIDS(sp, &gdlp->dl_headSolid) {
+ bu_vls_printf(vls, "-1 %d %d %d\n",
+ sp->s_color[0],
+ sp->s_color[1],
+ sp->s_color[2]);
+
+ /* Print the actual vector list */
+ for (BU_LIST_FOR(vp, bn_vlist, &(sp->s_vlist))) {
+ int i;
+ int nused = vp->nused;
+ int *cmd = vp->cmd;
+ point_t *pt = vp->pt;
+
+ BN_CK_VLIST(vp);
+
+ for (i = 0; i < nused; i++, cmd++, pt++)
+ bu_vls_printf(vls, "%d %g %g %g\n", *cmd, V3ARGS(*pt));
+ }
+ }
+
+ gdlp = next_gdlp;
+ }
+
+ }
+}
+
+void
+dl_bitwise_and_fullpath(struct bu_list *hdlp, int flag_val)
+{
+ struct display_list *gdlp;
+ struct display_list *next_gdlp;
+ size_t i;
+ struct solid *sp;
+
+ gdlp = BU_LIST_NEXT(display_list, hdlp);
+ while (BU_LIST_NOT_HEAD(gdlp, hdlp)) {
+ next_gdlp = BU_LIST_PNEXT(display_list, gdlp);
+
+ FOR_ALL_SOLIDS(sp, &gdlp->dl_headSolid) {
+ for (i = 0; i < sp->s_fullpath.fp_len; i++) {
+ DB_FULL_PATH_GET(&sp->s_fullpath, i)->d_flags &= flag_val;
+ }
+ }
+
+ gdlp = next_gdlp;
+ }
+}
+
+void
+dl_write_animate(struct bu_list *hdlp, FILE *fp)
+{
+ struct display_list *gdlp;
+ struct display_list *next_gdlp;
+ size_t i;
+ struct solid *sp;
+
+ gdlp = BU_LIST_NEXT(display_list, hdlp);
+ while (BU_LIST_NOT_HEAD(gdlp, hdlp)) {
+ next_gdlp = BU_LIST_PNEXT(display_list, gdlp);
+
+ FOR_ALL_SOLIDS(sp, &gdlp->dl_headSolid) {
+ for (i = 0; i < sp->s_fullpath.fp_len; i++) {
+ if (!(DB_FULL_PATH_GET(&sp->s_fullpath, i)->d_flags &
RT_DIR_USED)) {
+ struct animate *anp;
+ for (anp = DB_FULL_PATH_GET(&sp->s_fullpath,
i)->d_animate; anp;
+ anp=anp->an_forw) {
+ db_write_anim(fp, anp);
+ }
+ DB_FULL_PATH_GET(&sp->s_fullpath, i)->d_flags |=
RT_DIR_USED;
+ }
+ }
+ }
+
+ gdlp = next_gdlp;
+ }
+}
+
+
+
+int
+dl_select(struct bu_list *hdlp, mat_t model2view, struct bu_vls *vls, double
vx, double vy, double vwidth, double vheight, int rflag)
+{
+ struct display_list *gdlp = NULL;
+ struct display_list *next_gdlp = NULL;
+ struct solid *sp = NULL;
+ fastf_t vr = 0.0;
+ fastf_t vmin_x = 0.0;
+ fastf_t vmin_y = 0.0;
+ fastf_t vmax_x = 0.0;
+ fastf_t vmax_y = 0.0;
+
+ if (rflag) {
+ vr = vwidth;
+ } else {
+ vmin_x = vx;
+ vmin_y = vy;
+
+ if (vwidth > 0)
+ vmax_x = vx + vwidth;
+ else {
+ vmin_x = vx + vwidth;
+ vmax_x = vx;
+ }
+
+ if (vheight > 0)
+ vmax_y = vy + vheight;
+ else {
+ vmin_y = vy + vheight;
+ vmax_y = vy;
+ }
+ }
+
+ gdlp = BU_LIST_NEXT(display_list, hdlp);
+ while (BU_LIST_NOT_HEAD(gdlp, hdlp)) {
+ next_gdlp = BU_LIST_PNEXT(display_list, gdlp);
+
+ FOR_ALL_SOLIDS(sp, &gdlp->dl_headSolid) {
+ point_t vmin, vmax;
+ struct bn_vlist *vp;
+
+ vmax[X] = vmax[Y] = vmax[Z] = -INFINITY;
+ vmin[X] = vmin[Y] = vmin[Z] = INFINITY;
+
+ for (BU_LIST_FOR(vp, bn_vlist, &(sp->s_vlist))) {
+ int j;
+ int nused = vp->nused;
+ int *cmd = vp->cmd;
+ point_t *pt = vp->pt;
+ point_t vpt;
+ for (j = 0; j < nused; j++, cmd++, pt++) {
+ switch (*cmd) {
+ case BN_VLIST_POLY_START:
+ case BN_VLIST_POLY_VERTNORM:
+ case BN_VLIST_TRI_START:
+ case BN_VLIST_TRI_VERTNORM:
+ case BN_VLIST_POINT_SIZE:
+ case BN_VLIST_LINE_WIDTH:
+ /* attribute, not location */
+ break;
+ case BN_VLIST_LINE_MOVE:
+ case BN_VLIST_LINE_DRAW:
+ case BN_VLIST_POLY_MOVE:
+ case BN_VLIST_POLY_DRAW:
+ case BN_VLIST_POLY_END:
+ case BN_VLIST_TRI_MOVE:
+ case BN_VLIST_TRI_DRAW:
+ case BN_VLIST_TRI_END:
+ MAT4X3PNT(vpt, model2view, *pt);
+ V_MIN(vmin[X], vpt[X]);
+ V_MAX(vmax[X], vpt[X]);
+ V_MIN(vmin[Y], vpt[Y]);
+ V_MAX(vmax[Y], vpt[Y]);
+ V_MIN(vmin[Z], vpt[Z]);
+ V_MAX(vmax[Z], vpt[Z]);
+ break;
+ default: {
+ bu_vls_printf(vls, "unknown vlist op %d\n", *cmd);
+ }
+ }
+ }
+ }
+
+ if (rflag) {
+ point_t vloc;
+ vect_t diff;
+ fastf_t mag;
+
+ VSET(vloc, vx, vy, vmin[Z]);
+ VSUB2(diff, vmin, vloc);
+ mag = MAGNITUDE(diff);
+
+ if (mag > vr)
+ continue;
+
+ VSET(vloc, vx, vy, vmax[Z]);
+ VSUB2(diff, vmax, vloc);
+ mag = MAGNITUDE(diff);
+
+ if (mag > vr)
+ continue;
+
+ db_path_to_vls(vls, &sp->s_fullpath);
+ bu_vls_printf(vls, "\n");
+ } else {
+ if (vmin_x <= vmin[X] && vmax[X] <= vmax_x &&
+ vmin_y <= vmin[Y] && vmax[Y] <= vmax_y) {
+ db_path_to_vls(vls, &sp->s_fullpath);
+ bu_vls_printf(vls, "\n");
+ }
+ }
+ }
+
+ gdlp = next_gdlp;
+ }
+
+ return GED_OK;
+}
+
+int
+dl_select_partial(struct bu_list *hdlp, mat_t model2view, struct bu_vls *vls,
double vx, double vy, double vwidth, double vheight, int rflag)
+{
+ struct display_list *gdlp = NULL;
+ struct display_list *next_gdlp = NULL;
+ struct solid *sp = NULL;
+ fastf_t vr = 0.0;
+ fastf_t vmin_x = 0.0;
+ fastf_t vmin_y = 0.0;
+ fastf_t vmax_x = 0.0;
+ fastf_t vmax_y = 0.0;
+
+ if (rflag) {
+ vr = vwidth;
+ } else {
+ vmin_x = vx;
+ vmin_y = vy;
+
+ if (vwidth > 0)
+ vmax_x = vx + vwidth;
+ else {
+ vmin_x = vx + vwidth;
+ vmax_x = vx;
+ }
+
+ if (vheight > 0)
+ vmax_y = vy + vheight;
+ else {
+ vmin_y = vy + vheight;
+ vmax_y = vy;
+ }
+ }
+
+ gdlp = BU_LIST_NEXT(display_list, hdlp);
+ while (BU_LIST_NOT_HEAD(gdlp, hdlp)) {
+ next_gdlp = BU_LIST_PNEXT(display_list, gdlp);
+
+ FOR_ALL_SOLIDS(sp, &gdlp->dl_headSolid) {
+ struct bn_vlist *vp;
+
+ for (BU_LIST_FOR(vp, bn_vlist, &(sp->s_vlist))) {
+ int j;
+ int nused = vp->nused;
+ int *cmd = vp->cmd;
+ point_t *pt = vp->pt;
+ point_t vpt;
+ for (j = 0; j < nused; j++, cmd++, pt++) {
+ switch (*cmd) {
+ case BN_VLIST_POLY_START:
+ case BN_VLIST_POLY_VERTNORM:
+ case BN_VLIST_TRI_START:
+ case BN_VLIST_TRI_VERTNORM:
+ /* Has normal vector, not location */
+ break;
+ case BN_VLIST_LINE_MOVE:
+ case BN_VLIST_LINE_DRAW:
+ case BN_VLIST_POLY_MOVE:
+ case BN_VLIST_POLY_DRAW:
+ case BN_VLIST_POLY_END:
+ case BN_VLIST_TRI_MOVE:
+ case BN_VLIST_TRI_DRAW:
+ case BN_VLIST_TRI_END:
+ MAT4X3PNT(vpt, model2view, *pt);
+
+ if (rflag) {
+ point_t vloc;
+ vect_t diff;
+ fastf_t mag;
+
+ VSET(vloc, vx, vy, vpt[Z]);
+ VSUB2(diff, vpt, vloc);
+ mag = MAGNITUDE(diff);
+
+ if (mag > vr)
+ continue;
+
+ db_path_to_vls(vls, &sp->s_fullpath);
+ bu_vls_printf(vls, "\n");
+
+ goto solid_done;
+ } else {
+ if (vmin_x <= vpt[X] && vpt[X] <= vmax_x &&
+ vmin_y <= vpt[Y] && vpt[Y] <= vmax_y) {
+ db_path_to_vls(vls, &sp->s_fullpath);
+ bu_vls_printf(vls, "\n");
+
+ goto solid_done;
+ }
+ }
+
+ break;
+ default: {
+ bu_vls_printf(vls, "unknown vlist op %d\n", *cmd);
+ }
+ }
+ }
+ }
+
+ solid_done:
+ ;
+ }
+
+ gdlp = next_gdlp;
+ }
+
+ return GED_OK;
+}
+
+
+void
+dl_set_transparency(struct bu_list *hdlp, struct directory **dpp, double
transparency, void (*callback)(struct display_list *))
+{
+ struct display_list *gdlp;
+ struct display_list *next_gdlp;
+ struct solid *sp;
+ size_t i;
+ struct directory **tmp_dpp;
+
+ gdlp = BU_LIST_NEXT(display_list, hdlp);
+ while (BU_LIST_NOT_HEAD(gdlp, hdlp)) {
+ next_gdlp = BU_LIST_PNEXT(display_list, gdlp);
+
+ FOR_ALL_SOLIDS(sp, &gdlp->dl_headSolid) {
+ for (i = 0, tmp_dpp = dpp;
+ i < sp->s_fullpath.fp_len && *tmp_dpp != RT_DIR_NULL;
+ ++i, ++tmp_dpp) {
+ if (sp->s_fullpath.fp_names[i] != *tmp_dpp)
+ break;
+ }
+
+ if (*tmp_dpp != RT_DIR_NULL)
+ continue;
+
+ /* found a match */
+ sp->s_transparency = transparency;
+
+ }
+
+ if (callback != GED_CREATE_VLIST_CALLBACK_PTR_NULL)
+ (*callback)(gdlp);
+
+ gdlp = next_gdlp;
+ }
+
+}
+
+void
+dl_botdump(struct bu_list *hdlp, struct db_i *dbip, FILE *fp, int fd, char
*file_ext, int output_type, int *red, int *green, int *blue, fastf_t *alpha)
+{
+ int ret;
+ mat_t mat;
+ struct display_list *gdlp;
+
+ MAT_IDN(mat);
+
+ for (BU_LIST_FOR(gdlp, display_list, hdlp)) {
+ struct solid *sp;
+
+ FOR_ALL_SOLIDS(sp, &gdlp->dl_headSolid) {
+ struct directory *dp;
+ struct rt_db_internal intern;
+ struct rt_bot_internal *bot;
+
+ dp = sp->s_fullpath.fp_names[sp->s_fullpath.fp_len-1];
+
+ /* get the internal form */
+ ret=rt_db_get_internal(&intern, dp, dbip, mat, &rt_uniresource);
+
+ if (ret < 0) {
+ bu_log("rt_get_internal failure %d on %s\n", ret, dp->d_namep);
+ continue;
+ }
+
+ if (ret != ID_BOT) {
+ bu_log("%s is not a bot (ignored)\n", dp->d_namep);
+ rt_db_free_internal(&intern);
+ continue;
+ }
+
+ /* Write out object color */
+ if (output_type == OTYPE_OBJ) {
+ (*red) = sp->s_color[0];
+ (*green) = sp->s_color[1];
+ (*blue) = sp->s_color[2];
+ (*alpha) = sp->s_transparency;
+ }
+
+ bot = (struct rt_bot_internal *)intern.idb_ptr;
+ _ged_bot_dump(dp, NULL, bot, fp, fd, file_ext, dbip->dbi_filename);
+ rt_db_free_internal(&intern);
+ }
+ }
+
+}
+
+/*
+ * Local Variables:
+ * mode: C
+ * tab-width: 8
+ * indent-tabs-mode: t
+ * c-file-style: "stroustrup"
+ * End:
+ * ex: shiftwidth=4 tabstop=8
+ */
Modified: brlcad/branches/gedplugins/src/libged/edbot/edbot.c
===================================================================
--- brlcad/branches/gedplugins/src/libged/edbot/edbot.c 2020-07-21 16:36:56 UTC
(rev 76391)
+++ brlcad/branches/gedplugins/src/libged/edbot/edbot.c 2020-07-21 17:17:07 UTC
(rev 76392)
@@ -32,6 +32,7 @@
#include "ged.h"
#include "wdb.h"
+#include "../ged_private.h"
int
ged_bot_edge_split(struct ged *gedp, int argc, const char *argv[])
Modified: brlcad/branches/gedplugins/src/libged/editit/editit.c
===================================================================
--- brlcad/branches/gedplugins/src/libged/editit/editit.c 2020-07-21
16:36:56 UTC (rev 76391)
+++ brlcad/branches/gedplugins/src/libged/editit/editit.c 2020-07-21
17:17:07 UTC (rev 76392)
@@ -39,6 +39,7 @@
#include "bu/file.h"
#include "bu/path.h"
#include "ged.h"
+#include "../ged_private.h"
#define WIN_EDITOR "\"c:/Program Files/Windows NT/Accessories/wordpad\""
#define MAC_EDITOR "/Applications/TextEdit.app/Contents/MacOS/TextEdit"
Modified: brlcad/branches/gedplugins/src/libged/edpipe/edpipe.c
===================================================================
--- brlcad/branches/gedplugins/src/libged/edpipe/edpipe.c 2020-07-21
16:36:56 UTC (rev 76391)
+++ brlcad/branches/gedplugins/src/libged/edpipe/edpipe.c 2020-07-21
17:17:07 UTC (rev 76392)
@@ -39,6 +39,7 @@
#include "ged.h"
#include "wdb.h"
+#include "../ged_private.h"
/*
* Returns the index for the pipe segment matching ps.
Modified: brlcad/branches/gedplugins/src/libged/ged_private.h
===================================================================
--- brlcad/branches/gedplugins/src/libged/ged_private.h 2020-07-21 16:36:56 UTC
(rev 76391)
+++ brlcad/branches/gedplugins/src/libged/ged_private.h 2020-07-21 17:17:07 UTC
(rev 76392)
@@ -143,7 +143,7 @@
};
-void vls_col_item(struct bu_vls *str, const char *cp);
+GED_EXPORT void vls_col_item(struct bu_vls *str, const char *cp);
GED_EXPORT void vls_col_eol(struct bu_vls *str);
/* defined in facedef.c */
@@ -150,7 +150,7 @@
GED_EXPORT extern int edarb_facedef(void *data, int argc, const char *argv[]);
/* defined in ged.c */
-extern void _ged_print_node(struct ged *gedp,
+GED_EXPORT extern void _ged_print_node(struct ged *gedp,
struct directory *dp,
size_t pathpos,
int indentSize,
@@ -197,12 +197,12 @@
/* Returns a bu_ptbl of all solids referenced by the display list */
extern struct bu_ptbl *dl_get_solids(struct display_list *gdlp);
-extern void dl_add_path(struct display_list *gdlp, int dashflag, fastf_t
transparency, int dmode, int hiddenLine, struct bu_list *vhead, const struct
db_full_path *pathp, struct db_tree_state *tsp, unsigned char
*wireframe_color_override, void (*callback)(struct solid *), struct solid
*freesolid);
+GED_EXPORT extern void dl_add_path(struct display_list *gdlp, int dashflag,
fastf_t transparency, int dmode, int hiddenLine, struct bu_list *vhead, const
struct db_full_path *pathp, struct db_tree_state *tsp, unsigned char
*wireframe_color_override, void (*callback)(struct solid *), struct solid
*freesolid);
-extern int dl_redraw(struct display_list *gdlp, struct db_i *dbip, struct
db_tree_state *tsp, struct bview *gvp, void (*callback)(struct display_list *),
int skip_subtractions);
+GED_EXPORT extern int dl_redraw(struct display_list *gdlp, struct db_i *dbip,
struct db_tree_state *tsp, struct bview *gvp, void (*callback)(struct
display_list *), int skip_subtractions);
GED_EXPORT extern union tree * append_solid_to_display_list(struct
db_tree_state *tsp, const struct db_full_path *pathp, struct rt_db_internal
*ip, void *client_data);
GED_EXPORT int dl_set_illum(struct display_list *gdlp, const char *obj, int
illum);
-void dl_set_flag(struct bu_list *hdlp, int flag);
+GED_EXPORT void dl_set_flag(struct bu_list *hdlp, int flag);
GED_EXPORT void dl_set_wflag(struct bu_list *hdlp, int wflag);
GED_EXPORT void dl_zap(struct bu_list *hdlp, struct db_i *dbip, void
(*callback)(unsigned int, int), struct solid *freesolid);
GED_EXPORT int dl_how(struct bu_list *hdlp, struct bu_vls *vls, struct
directory **dpp, int both);
@@ -218,9 +218,9 @@
GED_EXPORT void dl_bitwise_and_fullpath(struct bu_list *hdlp, int flag);
-void dl_write_animate(struct bu_list *hdlp, FILE *fp);
+GED_EXPORT void dl_write_animate(struct bu_list *hdlp, FILE *fp);
-int dl_select(struct bu_list *hdlp, mat_t model2view, struct bu_vls *vls,
double vx, double vy, double vwidth, double vheight, int rflag);
+GED_EXPORT int dl_select(struct bu_list *hdlp, mat_t model2view, struct bu_vls
*vls, double vx, double vy, double vwidth, double vheight, int rflag);
GED_EXPORT int dl_select_partial(struct bu_list *hdlp, mat_t model2view,
struct bu_vls *vls, double vx, double vy, double vwidth, double vheight, int
rflag);
GED_EXPORT void dl_set_transparency(struct bu_list *hdlp, struct directory
**dpp, double transparency, void (*callback)(struct display_list *));
@@ -239,7 +239,7 @@
struct bn_vlblock *vbp,
const char *name,
int copy);
-extern int _ged_drawtrees(struct ged *gedp,
+GED_EXPORT extern int _ged_drawtrees(struct ged *gedp,
int argc,
const char *argv[],
int kind,
@@ -251,7 +251,7 @@
struct _ged_client_data *dgcdp);
/* defined in edbot.c */
-extern int _ged_select_botpts(struct ged *gedp,
+GED_EXPORT extern int _ged_select_botpts(struct ged *gedp,
struct rt_bot_internal *botip,
double vx,
double vy,
@@ -300,7 +300,7 @@
extern char *_gd_densities_source;
/* defined in how.c */
-extern struct directory **_ged_build_dpp(struct ged *gedp,
+GED_EXPORT extern struct directory **_ged_build_dpp(struct ged *gedp,
const char *path);
/* defined in list.c */
@@ -309,24 +309,24 @@
int verbose);
/* defined in loadview.c */
-extern vect_t _ged_eye_model;
-extern mat_t _ged_viewrot;
-extern struct ged *_ged_current_gedp;
-extern int _ged_cm_vsize(const int argc,
+GED_EXPORT extern vect_t _ged_eye_model;
+GED_EXPORT extern mat_t _ged_viewrot;
+GED_EXPORT extern struct ged *_ged_current_gedp;
+GED_EXPORT extern int _ged_cm_vsize(const int argc,
const char **argv);
-extern int _ged_cm_eyept(const int argc,
+GED_EXPORT extern int _ged_cm_eyept(const int argc,
const char **argv);
-extern int _ged_cm_lookat_pt(const int argc,
+GED_EXPORT extern int _ged_cm_lookat_pt(const int argc,
const char **argv);
-extern int _ged_cm_vrot(const int argc,
+GED_EXPORT extern int _ged_cm_vrot(const int argc,
const char **argv);
-extern int _ged_cm_orientation(const int argc,
+GED_EXPORT extern int _ged_cm_orientation(const int argc,
const char **argv);
-extern int _ged_cm_set(const int argc,
+GED_EXPORT extern int _ged_cm_set(const int argc,
const char **argv);
-extern int _ged_cm_end(const int argc,
+GED_EXPORT extern int _ged_cm_end(const int argc,
const char **argv);
-extern int _ged_cm_null(const int argc,
+GED_EXPORT extern int _ged_cm_null(const int argc,
const char **argv);
/* defined in preview.c */
@@ -346,7 +346,7 @@
GED_EXPORT extern void _ged_rt_set_eye_model(struct ged *gedp,
vect_t eye_model);
GED_EXPORT extern int _ged_run_rt(struct ged *gdp, int cmd_len, const char
**gd_rt_cmd, int argc, const char **argv);
-extern void _ged_rt_write(struct ged *gedp,
+GED_EXPORT extern void _ged_rt_write(struct ged *gedp,
FILE *fp,
vect_t eye_model,
int argc,
@@ -353,35 +353,35 @@
const char **argv);
/* defined in rtcheck.c */
-extern void _ged_wait_status(struct bu_vls *logstr,
+GED_EXPORT extern void _ged_wait_status(struct bu_vls *logstr,
int status);
/* defined in rotate_eto.c */
-extern int _ged_rotate_eto(struct ged *gedp,
+GED_EXPORT extern int _ged_rotate_eto(struct ged *gedp,
struct rt_eto_internal *eto,
const char *attribute,
matp_t rmat);
/* defined in rotate_extrude.c */
-extern int _ged_rotate_extrude(struct ged *gedp,
+GED_EXPORT extern int _ged_rotate_extrude(struct ged *gedp,
struct rt_extrude_internal *extrude,
const char *attribute,
matp_t rmat);
/* defined in rotate_hyp.c */
-extern int _ged_rotate_hyp(struct ged *gedp,
+GED_EXPORT extern int _ged_rotate_hyp(struct ged *gedp,
struct rt_hyp_internal *hyp,
const char *attribute,
matp_t rmat);
/* defined in rotate_tgc.c */
-extern int _ged_rotate_tgc(struct ged *gedp,
+GED_EXPORT extern int _ged_rotate_tgc(struct ged *gedp,
struct rt_tgc_internal *tgc,
const char *attribute,
matp_t rmat);
/* defined in scale_ehy.c */
-extern int _ged_scale_ehy(struct ged *gedp,
+GED_EXPORT extern int _ged_scale_ehy(struct ged *gedp,
struct rt_ehy_internal *ehy,
const char *attribute,
fastf_t sf,
@@ -388,7 +388,7 @@
int rflag);
/* defined in scale_ell.c */
-extern int _ged_scale_ell(struct ged *gedp,
+GED_EXPORT extern int _ged_scale_ell(struct ged *gedp,
struct rt_ell_internal *ell,
const char *attribute,
fastf_t sf,
@@ -395,7 +395,7 @@
int rflag);
/* defined in scale_epa.c */
-extern int _ged_scale_epa(struct ged *gedp,
+GED_EXPORT extern int _ged_scale_epa(struct ged *gedp,
struct rt_epa_internal *epa,
const char *attribute,
fastf_t sf,
@@ -402,7 +402,7 @@
int rflag);
/* defined in scale_eto.c */
-extern int _ged_scale_eto(struct ged *gedp,
+GED_EXPORT extern int _ged_scale_eto(struct ged *gedp,
struct rt_eto_internal *eto,
const char *attribute,
fastf_t sf,
@@ -409,7 +409,7 @@
int rflag);
/* defined in scale_extrude.c */
-extern int _ged_scale_extrude(struct ged *gedp,
+GED_EXPORT extern int _ged_scale_extrude(struct ged *gedp,
struct rt_extrude_internal *extrude,
const char *attribute,
fastf_t sf,
@@ -416,7 +416,7 @@
int rflag);
/* defined in scale_hyp.c */
-extern int _ged_scale_hyp(struct ged *gedp,
+GED_EXPORT extern int _ged_scale_hyp(struct ged *gedp,
struct rt_hyp_internal *hyp,
const char *attribute,
fastf_t sf,
@@ -434,7 +434,7 @@
fastf_t sf);
/* defined in scale_part.c */
-extern int _ged_scale_part(struct ged *gedp,
+GED_EXPORT extern int _ged_scale_part(struct ged *gedp,
struct rt_part_internal *part,
const char *attribute,
fastf_t sf,
@@ -441,7 +441,7 @@
int rflag);
/* defined in edpipe.c */
-extern int _ged_scale_pipe(struct ged *gedp,
+GED_EXPORT extern int _ged_scale_pipe(struct ged *gedp,
struct rt_pipe_internal *pipe_internal,
const char *attribute,
fastf_t sf,
@@ -448,7 +448,7 @@
int rflag);
/* defined in scale_rhc.c */
-extern int _ged_scale_rhc(struct ged *gedp,
+GED_EXPORT extern int _ged_scale_rhc(struct ged *gedp,
struct rt_rhc_internal *rhc,
const char *attribute,
fastf_t sf,
@@ -455,7 +455,7 @@
int rflag);
/* defined in scale_rpc.c */
-extern int _ged_scale_rpc(struct ged *gedp,
+GED_EXPORT extern int _ged_scale_rpc(struct ged *gedp,
struct rt_rpc_internal *rpc,
const char *attribute,
fastf_t sf,
@@ -462,7 +462,7 @@
int rflag);
/* defined in scale_superell.c */
-extern int _ged_scale_superell(struct ged *gedp,
+GED_EXPORT extern int _ged_scale_superell(struct ged *gedp,
struct rt_superell_internal *superell,
const char *attribute,
fastf_t sf,
@@ -469,7 +469,7 @@
int rflag);
/* defined in scale_tgc.c */
-extern int _ged_scale_tgc(struct ged *gedp,
+GED_EXPORT extern int _ged_scale_tgc(struct ged *gedp,
struct rt_tgc_internal *tgc,
const char *attribute,
fastf_t sf,
@@ -476,7 +476,7 @@
int rflag);
/* defined in scale_tor.c */
-extern int _ged_scale_tor(struct ged *gedp,
+GED_EXPORT extern int _ged_scale_tor(struct ged *gedp,
struct rt_tor_internal *tor,
const char *attribute,
fastf_t sf,
@@ -483,7 +483,7 @@
int rflag);
/* defined in tops.c */
-struct directory **
+GED_EXPORT struct directory **
_ged_dir_getspace(struct db_i *dbip,
int num_entries);
@@ -495,7 +495,7 @@
int rflag);
/* defined in translate_tgc.c */
-extern int _ged_translate_tgc(struct ged *gedp,
+GED_EXPORT extern int _ged_translate_tgc(struct ged *gedp,
struct rt_tgc_internal *tgc,
const char *attribute,
vect_t tvec,
@@ -534,7 +534,7 @@
* _ged_results_add(gedp->ged_results, bu_vls_addr(my_vls_ptr));
*
*/
-extern int _ged_results_add(struct ged_results *results, const char
*result_string);
+GED_EXPORT extern int _ged_results_add(struct ged_results *results, const char
*result_string);
/* defined in ged_util.c */
@@ -542,7 +542,7 @@
* Given two pointers to pointers to directory entries, do a string
* compare on the respective names and return that value.
*/
-extern int cmpdirname(const void *a, const void *b, void *arg);
+GED_EXPORT extern int cmpdirname(const void *a, const void *b, void *arg);
/**
* Given two pointers to pointers to directory entries, compare
@@ -568,7 +568,7 @@
* by the argument if > 0.
*
*/
-extern struct directory ** _ged_getspace(struct db_i *dbip,
+GED_EXPORT extern struct directory ** _ged_getspace(struct db_i *dbip,
size_t num_entries);
/**
@@ -603,7 +603,7 @@
* pointer array and will stash found directory pointers there - caller must
make
* sure the allocated array is large enough to hold up to argc pointers.
*/
-extern int
+GED_EXPORT extern int
_ged_sort_existing_objs(struct ged *gedp, int argc, const char *argv[], struct
directory **dpa);
/* Ideally all of this could be in facetize.cpp, but the open() calls
Modified: brlcad/branches/gedplugins/src/libged/nmg_cmface/nmg_cmface.c
===================================================================
--- brlcad/branches/gedplugins/src/libged/nmg_cmface/nmg_cmface.c
2020-07-21 16:36:56 UTC (rev 76391)
+++ brlcad/branches/gedplugins/src/libged/nmg_cmface/nmg_cmface.c
2020-07-21 17:17:07 UTC (rev 76392)
@@ -39,7 +39,7 @@
struct vertex *v;
};
-int
+GED_EXPORT int
ged_nmg_cmface(struct ged *gedp, int argc, const char *argv[])
{
struct rt_db_internal internal;
Modified: brlcad/branches/gedplugins/src/libged/nmg_collapse/nmg_collapse.c
===================================================================
--- brlcad/branches/gedplugins/src/libged/nmg_collapse/nmg_collapse.c
2020-07-21 16:36:56 UTC (rev 76391)
+++ brlcad/branches/gedplugins/src/libged/nmg_collapse/nmg_collapse.c
2020-07-21 17:17:07 UTC (rev 76392)
@@ -33,7 +33,7 @@
@@ Diff output truncated at 100000 characters. @@
This was sent by the SourceForge.net collaborative development platform, the
world's largest Open Source development site.
_______________________________________________
BRL-CAD Source Commits mailing list
[email protected]
https://lists.sourceforge.net/lists/listinfo/brlcad-commits