Revision: 76289
http://sourceforge.net/p/brlcad/code/76289
Author: starseeker
Date: 2020-07-09 17:15:22 +0000 (Thu, 09 Jul 2020)
Log Message:
-----------
Start roughing in the asc input code as well (for v4 - v5 needs a rewrite.)
Modified Paths:
--------------
brlcad/trunk/src/libgcv/plugins/asc/asc_v4.cpp
brlcad/trunk/src/libgcv/plugins/asc/asc_v5.cpp
Modified: brlcad/trunk/src/libgcv/plugins/asc/asc_v4.cpp
===================================================================
--- brlcad/trunk/src/libgcv/plugins/asc/asc_v4.cpp 2020-07-09 16:15:58 UTC
(rev 76288)
+++ brlcad/trunk/src/libgcv/plugins/asc/asc_v4.cpp 2020-07-09 17:15:22 UTC
(rev 76289)
@@ -32,12 +32,1458 @@
#include <sstream>
#include <string>
+#include "bu/units.h"
#include "rt/db4.h"
#include "raytrace.h"
+#include "wdb.h"
#include "gcv/api.h"
#include "gcv/util.h"
+/* maximum input line buffer size */
+#define BUFSIZE (16*1024)
+#define SIZE (128*1024*1024)
+#define TYPE_LEN 200
+#define NAME_LEN 200
+
+
+char *ibuf = NULL;
+/* GED database record */
+static union record irecord;
+FILE *iifp = NULL;
+struct rt_wdb *iofp = NULL;
+
+/* Record input buffer */
+char NAME[NAME_LEN + 2] = {0};
+
+static int ars_ncurves = 0;
+static int ars_ptspercurve = 0;
+static int ars_curve = 0;
+static int ars_pt = 0;
+static char *ars_name = NULL;
+static fastf_t **ars_curves = NULL;
+
+static int linecnt = 0;
+
+char *
+nxt_spc(char *cp)
+{
+ while (*cp != ' ' && *cp != '\t' && *cp !='\0') {
+ cp++;
+ }
+ if (*cp != '\0') {
+ cp++;
+ }
+ return cp;
+}
+
+
int
+incr_ars_pnt(void)
+{
+ int ret=0;
+
+ ars_pt++;
+ if (ars_pt >= ars_ptspercurve) {
+ ars_curve++;
+ ars_pt = 0;
+ ret = 1;
+ }
+
+ if (ars_curve >= ars_ncurves)
+ return 2;
+
+ return ret;
+}
+
+
+/**
+ * This routine removes newline and carriage return characters from
+ * the ibuffer and substitutes in NULL.
+ */
+void
+zap_nl(void)
+{
+ char *bp;
+
+ bp = &ibuf[0];
+
+ while (*bp != '\0') {
+ if ((*bp == '\n') || (*bp == '\r')) {
+ *bp = '\0';
+ }
+ bp++;
+ }
+}
+
+
+/**
+ * Input format is:
+ * s type name args...\n
+ *
+ * Individual processing is needed for each 'type' of solid, to hand
+ * it off to the appropriate LIBWDB routine.
+ */
+void
+strsolbld(void)
+{
+ const struct rt_functab *ftp;
+ const char delim[] = " ";
+ const char end_delim[] = "\n";
+ char *type = NULL;
+ char *name = NULL;
+ char *args = NULL;
+#if defined(HAVE_WORKING_STRTOK_R_FUNCTION)
+ char *saveptr = NULL;
+#endif
+ struct bu_vls str = BU_VLS_INIT_ZERO;
+ char *ibuf2 = (char *)bu_malloc(sizeof(char) * BUFSIZE, "strsolbld
temporary ibuffer");
+ char *ibufp = ibuf2;
+
+ memcpy(ibuf2, ibuf, sizeof(char) * BUFSIZE);
+
+#if defined(HAVE_WORKING_STRTOK_R_FUNCTION)
+ /* this function is reentrant */
+ (void)strtok_r(ibuf2, delim, &saveptr); /* skip stringsolid_id */
+ type = strtok_r(NULL, delim, &saveptr);
+ name = strtok_r(NULL, delim, &saveptr);
+ args = strtok_r(NULL, end_delim, &saveptr);
+#else
+ (void)strtok(ibuf2, delim); /* skip stringsolid_id */
+ type = strtok(NULL, delim);
+ name = strtok(NULL, delim);
+ args = strtok(NULL, end_delim);
+#endif
+
+ if (BU_STR_EQUAL(type, "dsp")) {
+ struct rt_dsp_internal *dsp;
+
+ BU_ALLOC(dsp, struct rt_dsp_internal);
+ bu_vls_init(&dsp->dsp_name);
+ bu_vls_strcpy(&str, args);
+ if (bu_struct_parse(&str, OBJ[ID_DSP].ft_parsetab, (char *)dsp, NULL) <
0) {
+ bu_log("strsolbld(%s): Unable to parse %s solid's args of '%s'\n",
+ name, type, args);
+ ftp = rt_get_functab_by_label("dsp");
+ if (ftp && ftp->ft_ifree)
+ ftp->ft_ifree((struct rt_db_internal *)dsp);
+ goto out;
+ }
+ dsp->magic = RT_DSP_INTERNAL_MAGIC;
+ if (wdb_export(iofp, name, (void *)dsp, ID_DSP, mk_conv2mm) < 0) {
+ bu_log("strsolbld(%s): Unable to export %s solid, args='%s'\n",
+ name, type, args);
+ goto out;
+ }
+ /* 'dsp' has already been freed by wdb_export() */
+ } else if (BU_STR_EQUAL(type, "ebm")) {
+ struct rt_ebm_internal *ebm;
+
+ BU_ALLOC(ebm, struct rt_ebm_internal);
+
+ MAT_IDN(ebm->mat);
+
+ bu_vls_strcpy(&str, args);
+ if (bu_struct_parse(&str, OBJ[ID_EBM].ft_parsetab, (char *)ebm, NULL) <
0) {
+ bu_log("strsolbld(%s): Unable to parse %s solid's args of '%s'\n",
+ name, type, args);
+ ftp = rt_get_functab_by_label("ebm");
+ if (ftp && ftp->ft_ifree)
+ ftp->ft_ifree((struct rt_db_internal *)ebm);
+ return;
+ }
+ ebm->magic = RT_EBM_INTERNAL_MAGIC;
+ if (wdb_export(iofp, name, (void *)ebm, ID_EBM, mk_conv2mm) < 0) {
+ bu_log("strsolbld(%s): Unable to export %s solid, args='%s'\n",
+ name, type, args);
+ goto out;
+ }
+ /* 'ebm' has already been freed by wdb_export() */
+ } else if (BU_STR_EQUAL(type, "vol")) {
+ struct rt_vol_internal *vol;
+
+ BU_ALLOC(vol, struct rt_vol_internal);
+ MAT_IDN(vol->mat);
+
+ bu_vls_strcpy(&str, args);
+ if (bu_struct_parse(&str, OBJ[ID_VOL].ft_parsetab, (char *)vol, NULL) <
0) {
+ bu_log("strsolbld(%s): Unable to parse %s solid's args of '%s'\n",
+ name, type, args);
+ ftp = rt_get_functab_by_label("vol");
+ if (ftp && ftp->ft_ifree)
+ ftp->ft_ifree((struct rt_db_internal *)vol);
+ return;
+ }
+ vol->magic = RT_VOL_INTERNAL_MAGIC;
+ if (wdb_export(iofp, name, (void *)vol, ID_VOL, mk_conv2mm) < 0) {
+ bu_log("strsolbld(%s): Unable to export %s solid, args='%s'\n",
+ name, type, args);
+ goto out;
+ }
+ /* 'vol' has already been freed by wdb_export() */
+ } else {
+ bu_log("strsolbld(%s): unable to convert '%s' type solid, skipping\n",
+ name, type);
+ }
+
+out:
+ bu_free(ibufp, "strsolbld temporary ibuffer");
+ bu_vls_free(&str);
+}
+
+
+#define LSEG 'L'
+#define CARC 'A'
+#define NURB 'N'
+
+void
+sktbld(void)
+{
+ char *cp, *ptr;
+ size_t i, j;
+ unsigned long vert_count, seg_count;
+ float fV[3], fu[3], fv[3];
+ point_t V;
+ vect_t u, v;
+ point2d_t *verts;
+ char name[NAME_LEN+1];
+ struct rt_sketch_internal *skt;
+ struct rt_curve *crv;
+ struct line_seg *lsg;
+ struct carc_seg *csg;
+ struct nurb_seg *nsg;
+
+ cp = ibuf;
+
+ cp++;
+ cp++;
+
+ sscanf(cp, "%200s %f %f %f %f %f %f %f %f %f %lu %lu", /* NAME_LEN */
+ name,
+ &fV[0], &fV[1], &fV[2],
+ &fu[0], &fu[1], &fu[2],
+ &fv[0], &fv[1], &fv[2],
+ &vert_count, &seg_count);
+
+ VMOVE(V, fV);
+ VMOVE(u, fu);
+ VMOVE(v, fv);
+
+ if (bu_fgets(ibuf, BUFSIZE, iifp) == (char *)0)
+ bu_exit(-1, "Unexpected EOF while reading sketch (%s) data\n", name);
+
+ verts = (point2d_t *)bu_calloc(vert_count, sizeof(point2d_t), "verts");
+ ptr = strtok(ibuf, " ");
+ if (!ptr)
+ bu_exit(1, "ERROR: no vertices for sketch (%s)\n", name);
+ for (i=0; i<vert_count; i++) {
+ verts[i][0] = atof(ptr);
+ ptr = strtok((char *)NULL, " ");
+ if (!ptr)
+ bu_exit(1, "ERROR: not enough vertices for sketch (%s)\n", name);
+ verts[i][1] = atof(ptr);
+ ptr = strtok((char *)NULL, " ");
+ if (!ptr && i < vert_count-1)
+ bu_exit(1, "ERROR: not enough vertices for sketch (%s)\n", name);
+ }
+
+ BU_ALLOC(skt, struct rt_sketch_internal);
+ skt->magic = RT_SKETCH_INTERNAL_MAGIC;
+ VMOVE(skt->V, V);
+ VMOVE(skt->u_vec, u);
+ VMOVE(skt->v_vec, v);
+ skt->vert_count = vert_count;
+ skt->verts = verts;
+ crv = &skt->curve;
+ crv->count = seg_count;
+
+ crv->segment = (void **)bu_calloc(crv->count, sizeof(void *), "segments");
+ crv->reverse = (int *)bu_calloc(crv->count, sizeof(int), "reverse");
+ for (j=0; j<crv->count; j++) {
+ double radius;
+ int k;
+
+ if (bu_fgets(ibuf, BUFSIZE, iifp) == (char *)0)
+ bu_exit(-1, "Unexpected EOF while reading sketch (%s) data\n",
name);
+
+ cp = ibuf + 2;
+ switch (*cp) {
+ case LSEG:
+ BU_ALLOC(lsg, struct line_seg);
+ sscanf(cp+1, "%d %d %d", &crv->reverse[j], &lsg->start,
&lsg->end);
+ lsg->magic = CURVE_LSEG_MAGIC;
+ crv->segment[j] = lsg;
+ break;
+ case CARC:
+ BU_ALLOC(csg, struct carc_seg);
+ sscanf(cp+1, "%d %d %d %lf %d %d", &crv->reverse[j],
&csg->start, &csg->end,
+ &radius, &csg->center_is_left, &csg->orientation);
+ csg->radius = radius;
+ csg->magic = CURVE_CARC_MAGIC;
+ crv->segment[j] = csg;
+ break;
+ case NURB:
+ BU_ALLOC(nsg, struct nurb_seg);
+ sscanf(cp+1, "%d %d %d %d %d", &crv->reverse[j], &nsg->order,
&nsg->pt_type,
+ &nsg->k.k_size, &nsg->c_size);
+ nsg->k.knots = (fastf_t *)bu_calloc(nsg->k.k_size,
sizeof(fastf_t), "knots");
+ nsg->ctl_points = (int *)bu_calloc(nsg->c_size, sizeof(int),
"control points");
+ if (bu_fgets(ibuf, BUFSIZE, iifp) == (char *)0)
+ bu_exit(-1, "Unexpected EOF while reading sketch (%s)
data\n", name);
+ cp = ibuf + 3;
+ ptr = strtok(cp, " ");
+ if (!ptr)
+ bu_exit(1, "ERROR: not enough knots for nurb segment in
sketch (%s)\n", name);
+ for (k=0; k<nsg->k.k_size; k++) {
+ nsg->k.knots[k] = atof(ptr);
+ ptr = strtok((char *)NULL, " ");
+ if (!ptr && k<nsg->k.k_size-1)
+ bu_exit(1, "ERROR: not enough knots for nurb segment in
sketch (%s)\n", name);
+ }
+ if (bu_fgets(ibuf, BUFSIZE, iifp) == (char *)0)
+ bu_exit(-1, "Unexpected EOF while reading sketch (%s)
data\n", name);
+ cp = ibuf + 3;
+ ptr = strtok(cp, " ");
+ if (!ptr)
+ bu_exit(1, "ERROR: not enough control points for nurb
segment in sketch (%s)\n", name);
+ for (k=0; k<nsg->c_size; k++) {
+ nsg->ctl_points[k] = atoi(ptr);
+ ptr = strtok((char *)NULL, " ");
+ if (!ptr && k<nsg->c_size-1)
+ bu_exit(1, "ERROR: not enough control points for nurb
segment in sketch (%s)\n", name);
+ }
+ nsg->magic = CURVE_NURB_MAGIC;
+ crv->segment[j] = nsg;
+ break;
+ default:
+ bu_exit(1, "Unrecognized segment type (%c) in sketch (%s)\n",
*cp, name);
+ }
+
+ }
+
+ (void)mk_sketch(iofp, name, skt);
+}
+
+
+void
+extrbld(void)
+{
+ char *cp;
+ char name[NAME_LEN+1];
+ char sketch_name[NAME_LEN+1];
+ int keypoint;
+ float fV[3];
+ float fh[3];
+ float fu_vec[3], fv_vec[3];
+ point_t V;
+ vect_t h, u_vec, v_vec;
+
+ cp = ibuf;
+
+ cp++;
+
+ cp++;
+ sscanf(cp, "%200s %200s %d %f %f %f %f %f %f %f %f %f %f %f %f", /*
NAME_LEN */
+ name, sketch_name, &keypoint, &fV[0], &fV[1], &fV[2], &fh[0],
&fh[1], &fh[2],
+ &fu_vec[0], &fu_vec[1], &fu_vec[2], &fv_vec[0], &fv_vec[1],
&fv_vec[2]);
+
+ VMOVE(V, fV);
+ VMOVE(h, fh);
+ VMOVE(u_vec, fu_vec);
+ VMOVE(v_vec, fv_vec);
+ (void)mk_extrusion(iofp, name, sketch_name, V, h, u_vec, v_vec, keypoint);
+}
+
+
+/**
+ * For the time being, what we read in from the ascii form is a hex
+ * dump of the on-disk form of NMG. This is the same between v4 and
+ * v5. Reassemble it in v5 binary form here, then import it, then
+ * re-export it. This extra step is necessary because we don't know
+ * what version database the output it, LIBWDB is only interested in
+ * writing in-memory versions.
+ */
+void
+nmgbld(void)
+{
+ char *cp;
+ int version;
+ char *name;
+ long granules;
+ long struct_count[26];
+ struct bu_external ext;
+ struct rt_db_internal intern;
+ int j;
+
+ /* First, process the header line */
+ strtok(ibuf, " ");
+ /* This is nmg_id, unused here. */
+ cp = strtok(NULL, " ");
+ version = atoi(cp);
+ cp = strtok(NULL, " ");
+ name = bu_strdup(cp);
+ cp = strtok(NULL, " ");
+ granules = atol(cp);
+
+ /* Allocate storage for external v5 form of the body */
+ BU_EXTERNAL_INIT(&ext);
+ ext.ext_nbytes = SIZEOF_NETWORK_LONG + 26*SIZEOF_NETWORK_LONG + 128 *
granules;
+ ext.ext_buf = (uint8_t *)bu_malloc(ext.ext_nbytes, "nmg ext_buf");
+ *(uint32_t *)ext.ext_buf = htonl(version);
+ BU_ASSERT(version == 1); /* DISK_MODEL_VERSION */
+
+ /* Get next line of input with the 26 counts on it */
+ if (bu_fgets(ibuf, BUFSIZE, iifp) == (char *)0)
+ bu_exit(-1, "Unexpected EOF while reading NMG %s data, line 2\n", name);
+
+ /* Second, process counts for each kind of structure */
+ cp = strtok(ibuf, " ");
+ for (j=0; j<26; j++) {
+ struct_count[j] = atol(cp);
+ *(uint32_t *)(ext.ext_buf + SIZEOF_NETWORK_LONG*(j+1)) =
htonl(struct_count[j]);
+ cp = strtok((char *)NULL, " ");
+ }
+
+ /* Remaining lines have 32 bytes per line, in hex */
+ /* There are 4 lines to make up one granule */
+ cp = ((char *)ext.ext_buf) + (26+1)*SIZEOF_NETWORK_LONG;
+ for (j=0; j < granules * 4; j++) {
+ int k;
+ unsigned int cp_i;
+
+ if (bu_fgets(ibuf, BUFSIZE, iifp) == (char *)0)
+ bu_exit(-1, "Unexpected EOF while reading NMG %s data, hex line
%d\n", name, j);
+
+ for (k=0; k<32; k++) {
+ sscanf(&ibuf[k*2], "%2x", &cp_i);
+ *cp++ = cp_i;
+ }
+ }
+
+ /* Next, import this disk record into memory */
+ RT_DB_INTERNAL_INIT(&intern);
+ if (OBJ[ID_NMG].ft_import5(&intern, &ext, bn_mat_identity, iofp->dbip,
&rt_uniresource) < 0)
+ bu_exit(-1, "ft_import5 failed on NMG %s\n", name);
+ bu_free_external(&ext);
+
+ /* Now we should have a good NMG in memory */
+ nmg_vmodel((struct model *)intern.idb_ptr);
+
+ /* Finally, squirt it back out through LIBWDB */
+ mk_nmg(iofp, name, (struct model *)intern.idb_ptr);
+ /* mk_nmg() frees the intern.idp_ptr pointer */
+ RT_DB_INTERNAL_INIT(&intern);
+
+ bu_free(name, "name");
+}
+
+
+/**
+ * This routine parses a solid record and determines which libwdb
+ * routine to call to replicate this solid. Simple primitives are
+ * expected.
+ */
+void
+solbld(void)
+{
+ char *cp;
+ char *np;
+ int i;
+
+ char s_type; /* id for the type of primitive */
+ fastf_t val[24]; /* array of values/parameters for solid */
+ point_t center; /* center; used by many solids */
+ point_t pnts[9]; /* array of points for the arbs */
+ point_t norm;
+ vect_t a, b, c, d, n; /* various vectors required */
+ vect_t height; /* height vector for tgc */
+ vect_t breadth; /* breadth vector for rpc */
+ double dd, rad1, rad2;
+
+ cp = ibuf;
+ cp++; /* ident */
+ cp = nxt_spc(cp); /* skip the space */
+ s_type = atoi(cp);
+
+ cp = nxt_spc(cp);
+
+ np = NAME;
+ while (*cp != ' ') {
+ *np++ = *cp++;
+ }
+ *np = '\0';
+
+ cp = nxt_spc(cp);
+ /* Comgeom solid type */
+
+ for (i = 0; i < 24; i++) {
+ cp = nxt_spc(cp);
+ val[i] = atof(cp);
+ }
+
+ /* Switch on the record type to make the solids. */
+
+ switch (s_type) {
+
+ case GRP:
+ VSET(center, val[0], val[1], val[2]);
+ VSET(n, val[3], val[4], val[5]);
+ (void)mk_grip(iofp, NAME, center, n, val[6]);
+ break;
+
+ case TOR:
+ VSET(center, val[0], val[1], val[2]);
+ VSET(n, val[3], val[4], val[5]);
+ rad1 = MAGNITUDE(&val[6]);
+ rad2 = MAGNITUDE(n);
+ VUNITIZE(n);
+
+ /* Prevent illegal torii from floating point fuzz */
+ V_MIN(rad2, rad1);
+
+ mk_tor(iofp, NAME, center, n, rad1, rad2);
+ break;
+
+ case GENTGC:
+ VSET(center, val[0], val[1], val[2]);
+ VSET(height, val[3], val[4], val[5]);
+ VSET(a, val[6], val[7], val[8]);
+ VSET(b, val[9], val[10], val[11]);
+ VSET(c, val[12], val[13], val[14]);
+ VSET(d, val[15], val[16], val[17]);
+
+ mk_tgc(iofp, NAME, center, height, a, b, c, d);
+ break;
+
+ case GENELL:
+ VSET(center, val[0], val[1], val[2]);
+ VSET(a, val[3], val[4], val[5]);
+ VSET(b, val[6], val[7], val[8]);
+ VSET(c, val[9], val[10], val[11]);
+
+ mk_ell(iofp, NAME, center, a, b, c);
+ break;
+
+ case GENARB8:
+ VSET(pnts[0], val[0], val[1], val[2]);
+ VSET(pnts[1], val[3], val[4], val[5]);
+ VSET(pnts[2], val[6], val[7], val[8]);
+ VSET(pnts[3], val[9], val[10], val[11]);
+ VSET(pnts[4], val[12], val[13], val[14]);
+ VSET(pnts[5], val[15], val[16], val[17]);
+ VSET(pnts[6], val[18], val[19], val[20]);
+ VSET(pnts[7], val[21], val[22], val[23]);
+
+ /* Convert from vector notation to absolute points */
+ for (i=1; i<8; i++) {
+ VADD2(pnts[i], pnts[i], pnts[0]);
+ }
+
+ mk_arb8(iofp, NAME, &pnts[0][X]);
+ break;
+
+ case HALFSPACE:
+ VSET(norm, val[0], val[1], val[2]);
+ dd = val[3];
+
+ mk_half(iofp, NAME, norm, dd);
+ break;
+
+ case RPC:
+ VSET(center, val[0], val[1], val[2]);
+ VSET(height, val[3], val[4], val[5]);
+ VSET(breadth, val[6], val[7], val[8]);
+ dd = val[9];
+
+ mk_rpc(iofp, NAME, center, height, breadth, dd);
+ break;
+
+ case RHC:
+ VSET(center, val[0], val[1], val[2]);
+ VSET(height, val[3], val[4], val[5]);
+ VSET(breadth, val[6], val[7], val[8]);
+ rad1 = val[9];
+ dd = val[10];
+
+ mk_rhc(iofp, NAME, center, height, breadth, rad1, dd);
+ break;
+
+ case EPA:
+ VSET(center, val[0], val[1], val[2]);
+ VSET(height, val[3], val[4], val[5]);
+ VSET(a, val[6], val[7], val[8]);
+ VUNITIZE(a);
+ rad1 = val[9];
+ rad2 = val[10];
+
+ mk_epa(iofp, NAME, center, height, a, rad1, rad2);
+ break;
+
+ case EHY:
+ VSET(center, val[0], val[1], val[2]);
+ VSET(height, val[3], val[4], val[5]);
+ VSET(a, val[6], val[7], val[8]);
+ VUNITIZE(a);
+ rad1 = val[9];
+ rad2 = val[10];
+ dd = val[11];
+
+ mk_ehy(iofp, NAME, center, height, a, rad1, rad2, dd);
+ break;
+
+ case HYP:
+ VSET(center, val[0], val[1], val[2]);
+ VSET(height, val[3], val[4], val[5]);
+ VSET(a, val[6], val[7], val[8]);
+ rad1 = val[9];
+ rad2 = val[10];
+
+ mk_hyp(iofp, NAME, center, height, a, rad1, rad2);
+ break;
+
+ case ETO:
+ VSET(center, val[0], val[1], val[2]);
+ VSET(norm, val[3], val[4], val[5]);
+ VSET(c, val[6], val[7], val[8]);
+ rad1 = val[9];
+ rad2 = val[10];
+
+ mk_eto(iofp, NAME, center, norm, c, rad1, rad2);
+ break;
+
+ default:
+ bu_log("asc2g: bad solid %s s_type= %d, skipping\n",
+ NAME, s_type);
+ }
+
+}
+
+
+/**
+ * This routine invokes libwdb to build a member of a combination.
+ * Called only from combbld()
+ */
+void
+membbld(struct bu_list *headp)
+{
+ char *cp;
+ char *np;
+ int i;
+ char relation; /* boolean operation */
+ char inst_name[NAME_LEN+2];
+ struct wmember *memb;
+
+ cp = ibuf;
+ cp++; /* ident */
+ cp = nxt_spc(cp); /* skip the space */
+
+ relation = *cp++;
+ cp = nxt_spc(cp);
+
+ np = inst_name;
+ while (*cp != ' ') {
+ *np++ = *cp++;
+ }
+ *np = '\0';
+
+ cp = nxt_spc(cp);
+
+ memb = mk_addmember(inst_name, headp, NULL, relation);
+
+ for (i = 0; i < 16; i++) {
+ memb->wm_mat[i] = atof(cp);
+ cp = nxt_spc(cp);
+ }
+}
+
+
+/**
+ * This routine builds combinations. It does so by processing the "C"
+ * combination input line, (which may be followed by optional material
+ * properties lines), and it then slurps up any following "M" member
+ * lines, building up a linked list of all members. Reading continues
+ * until a non-"M" record is encountered.
+ *
+ * Returns -
+ * 0 OK
+ * 1 OK, another record exists in global input line ibuffer.
+ */
+int
+combbld(void)
+{
+ struct bu_list head;
+ char *cp = NULL;
+ char *np = NULL;
+ /* indicators for optional fields */
+ int temp_nflag = 0;
+ int temp_pflag = 0;
+
+ char override = 0;
+ char reg_flags; /* region flag */
+ int is_reg;
+ short regionid;
+ short aircode;
+ short material; /* GIFT material code */
+ short los; /* LOS estimate */
+ unsigned char rgb[3]; /* Red, green, blue values */
+ char matname[32]; /* String of material name */
+ char matparm[60]; /* String of material parameters */
+ char inherit; /* Inheritance property */
+
+ /* Set all flags initially. */
+ BU_LIST_INIT(&head);
+
+ cp = ibuf;
+ cp++; /* ID_COMB */
+ cp = nxt_spc(cp); /* skip the space */
+
+ reg_flags = *cp++; /* Y, N, or new P, F */
+ cp = nxt_spc(cp);
+
+ np = NAME;
+ while (*cp != ' ') {
+ *np++ = *cp++;
+ }
+ *np = '\0';
+
+ cp = nxt_spc(cp);
+
+ regionid = (short)atoi(cp);
+ cp = nxt_spc(cp);
+ aircode = (short)atoi(cp);
+ cp = nxt_spc(cp);
+ /* DEPRECATED: number of members expected */
+ cp = nxt_spc(cp);
+ /* DEPRECATED: Comgeom reference number */
+ cp = nxt_spc(cp);
+ material = (short)atoi(cp);
+ cp = nxt_spc(cp);
+ los = (short)atoi(cp);
+ cp = nxt_spc(cp);
+ override = (char)atoi(cp);
+ cp = nxt_spc(cp);
+
+ rgb[0] = (unsigned char)atoi(cp);
+ cp = nxt_spc(cp);
+ rgb[1] = (unsigned char)atoi(cp);
+ cp = nxt_spc(cp);
+ rgb[2] = (unsigned char)atoi(cp);
+ cp = nxt_spc(cp);
+
+ temp_nflag = atoi(cp);
+ cp = nxt_spc(cp);
+ temp_pflag = atoi(cp);
+
+ cp = nxt_spc(cp);
+ inherit = atoi(cp);
+
+ /* To support FASTGEN, different kinds of regions now exist. */
+ switch (reg_flags) {
+ case 'Y':
+ case 'R':
+ is_reg = DBV4_REGION;
+ break;
+ case 'P':
+ is_reg = DBV4_REGION_FASTGEN_PLATE;
+ break;
+ case 'V':
+ is_reg = DBV4_REGION_FASTGEN_VOLUME;
+ break;
+ case 'N':
+ default:
+ is_reg = 0;
+ }
+
+ if (temp_nflag) {
+ bu_fgets(ibuf, BUFSIZE, iifp);
+ zap_nl();
+ memset(matname, 0, sizeof(matname));
+ bu_strlcpy(matname, ibuf, sizeof(matname));
+ }
+ if (temp_pflag) {
+ bu_fgets(ibuf, BUFSIZE, iifp);
+ zap_nl();
+ memset(matparm, 0, sizeof(matparm));
+ bu_strlcpy(matparm, ibuf, sizeof(matparm));
+ }
+
+ for (;;) {
+ ibuf[0] = '\0';
+ if (bu_fgets(ibuf, BUFSIZE, iifp) == (char *)0)
+ break;
+
+ if (ibuf[0] != ID_MEMB) break;
+
+ /* Process (and accumulate) the members */
+ membbld(&head);
+ }
+
+ /* Spit them out, all at once. Use GIFT semantics. */
+ if (mk_comb(iofp, NAME, &head, is_reg,
+ temp_nflag ? matname : (char *)0,
+ temp_pflag ? matparm : (char *)0,
+ override ? (unsigned char *)rgb : (unsigned char *)0,
+ regionid, aircode, material, los, inherit, 0, 1) < 0) {
+ bu_exit(1, "asc2g: mk_lrcomb fail\n");
+ }
+
+ if (ibuf[0] == '\0') return 0;
+ return 1;
+}
+
+
+/**
+ * This routine builds ARS's.
+ */
+void
+arsabld(void)
+{
+ char *cp;
+ char *np;
+ int i;
+
+ if (ars_name)
+ bu_free((char *)ars_name, "ars_name");
+ cp = ibuf;
+ cp = nxt_spc(cp);
+ cp = nxt_spc(cp);
+
+ np = cp;
+ while (*(++cp) != ' ');
+ *cp++ = '\0';
+ ars_name = bu_strdup(np);
+ ars_ncurves = (short)atoi(cp);
+ cp = nxt_spc(cp);
+ ars_ptspercurve = (short)atoi(cp);
+
+ ars_curves = (fastf_t **)bu_calloc((ars_ncurves+1), sizeof(fastf_t *),
"ars_curves");
+ for (i=0; i<ars_ncurves; i++) {
+ ars_curves[i] = (fastf_t *)bu_calloc(ars_ptspercurve + 1,
+ sizeof(fastf_t) *
ELEMENTS_PER_VECT, "ars_curve");
+ }
+
+ ars_pt = 0;
+ ars_curve = 0;
+}
+
+
+/**
+ * This is the second half of the ARS-building. It builds the ARS B
+ * record.
+ */
+void
+arsbbld(void)
+{
+ char *cp;
+ int i;
+ int incr_ret;
+
+ cp = ibuf;
+ cp = nxt_spc(cp); /* skip the space */
+ cp = nxt_spc(cp);
+ cp = nxt_spc(cp);
+ for (i = 0; i < 8; i++) {
+ cp = nxt_spc(cp);
+ ars_curves[ars_curve][ars_pt*3] = atof(cp);
+ cp = nxt_spc(cp);
+ ars_curves[ars_curve][ars_pt*3 + 1] = atof(cp);
+ cp = nxt_spc(cp);
+ ars_curves[ars_curve][ars_pt*3 + 2] = atof(cp);
+ if (ars_curve > 0 || ars_pt > 0)
+ VADD2(&ars_curves[ars_curve][ars_pt*3],
&ars_curves[ars_curve][ars_pt*3], &ars_curves[0][0]);
+
+ incr_ret = incr_ars_pnt();
+ if (incr_ret == 2) {
+ /* finished, write out the ARS solid */
+ if (mk_ars(iofp, ars_name, ars_ncurves, ars_ptspercurve,
ars_curves)) {
+ bu_exit(1, "Failed trying to make ARS (%s)\n", ars_name);
+ }
+ return;
+ } else if (incr_ret == 1) {
+ /* end of curve, ignore remainder of record */
+ return;
+ }
+ }
+}
+
+
+/**
+ * This routine makes an ident record. It calls libwdb to do this.
+ */
+void
+identbld(void)
+{
+ char *cp;
+ char *np;
+ char units; /* units code number */
+ char version[6] = {0};
+ char title[255] = {0};
+ char unit_str[8] = {0};
+ double local2mm;
+
+ bu_strlcpy(unit_str, "none", sizeof(unit_str));
+
+ cp = ibuf;
+ cp++; /* ident */
+ cp = nxt_spc(cp); /* skip the space */
+
+ units = (char)atoi(cp);
+ cp = nxt_spc(cp);
+
+ /* Note that there is no provision for handing libwdb the version.
+ * However, this is automatically provided when needed.
+ */
+
+ np = version;
+ while (*cp != '\n' && *cp != '\r' && *cp != '\0') {
+ *np++ = *cp++;
+ }
+ *np = '\0';
+
+ if (!BU_STR_EQUAL(version, ID_VERSION)) {
+ bu_log("WARNING: input file version (%s) is not %s\n",
+ version, ID_VERSION);
+ }
+
+ (void)bu_fgets(ibuf, BUFSIZE, iifp);
+ zap_nl();
+ bu_strlcpy(title, ibuf, sizeof(title));
+
+ /* FIXME: Should use db_conversions() for this */
+ switch (units) {
+ case ID_NO_UNIT:
+ bu_strlcpy(unit_str, "mm", sizeof(unit_str));
+ break;
+ case ID_MM_UNIT:
+ bu_strlcpy(unit_str, "mm", sizeof(unit_str));
+ break;
+ case ID_UM_UNIT:
+ bu_strlcpy(unit_str, "um", sizeof(unit_str));
+ break;
+ case ID_CM_UNIT:
+ bu_strlcpy(unit_str, "cm", sizeof(unit_str));
+ break;
+ case ID_M_UNIT:
+ bu_strlcpy(unit_str, "m", sizeof(unit_str));
+ break;
+ case ID_KM_UNIT:
+ bu_strlcpy(unit_str, "km", sizeof(unit_str));
+ break;
+ case ID_IN_UNIT:
+
+ bu_strlcpy(unit_str, "in", sizeof(unit_str));
+ break;
+ case ID_FT_UNIT:
+ bu_strlcpy(unit_str, "ft", sizeof(unit_str));
+ break;
+ case ID_YD_UNIT:
+ bu_strlcpy(unit_str, "yard", sizeof(unit_str));
+ break;
+ case ID_MI_UNIT:
+ bu_strlcpy(unit_str, "mile", sizeof(unit_str));
+ break;
+ default:
+ fprintf(stderr, "asc2g: unknown v4 units code = %d, defaulting to
millimeters\n", units);
+ bu_strlcpy(unit_str, "mm", sizeof(unit_str));
+ }
+ local2mm = bu_units_conversion(unit_str);
+ if (local2mm <= 0) {
+ fprintf(stderr, "asc2g: unable to convert v4 units string '%s', got
local2mm=%g\n",
+ unit_str, local2mm);
+ bu_exit(3, NULL);
+ }
+
+ if (mk_id_editunits(iofp, title, local2mm) < 0)
+ bu_exit(2, "asc2g: unable to write database ID\n");
+}
+
+
+/**
+ * Collect up all the information for a POLY-solid. These are handled
+ * as BoT solids in v5, but we still have to read the data in the old
+ * format, and then convert it.
+ *
+ * The poly header line is followed by an unknown number of poly data
+ * lines.
+ */
+void
+polyhbld(void)
+{
+ char *cp;
+ char *name;
+ b_off_t startpos;
+ size_t nlines;
+ struct rt_pg_internal *pg;
+ struct rt_db_internal intern;
+ struct bn_tol tol;
+
+ (void)strtok(ibuf, " "); /* skip the ident character */
+ cp = strtok(NULL, " \n");
+ name = bu_strdup(cp);
+
+ /* Count up the number of poly data lines which follow */
+ startpos = bu_ftell(iifp);
+ for (nlines = 0;; nlines++) {
+ if (bu_fgets(ibuf, BUFSIZE, iifp) == NULL) break;
+ if (ibuf[0] != ID_P_DATA) break; /* 'Q' */
+ }
+ BU_ASSERT(nlines > 0);
+
+ /* Allocate storage for the faces */
+ BU_ALLOC(pg, struct rt_pg_internal);
+ pg->magic = RT_PG_INTERNAL_MAGIC;
+ pg->npoly = nlines;
+ pg->poly = (struct rt_pg_face_internal *)bu_calloc(pg->npoly,
+ sizeof(struct
rt_pg_face_internal), "poly[]");
+ pg->max_npts = 0;
+
+ /* Return to first 'Q' record */
+ bu_fseek(iifp, startpos, 0);
+
+ for (nlines = 0; nlines < pg->npoly; nlines++) {
+ struct rt_pg_face_internal *fp = &pg->poly[nlines];
+ int i;
+
+ if (bu_fgets(ibuf, BUFSIZE, iifp) == NULL) break;
+ if (ibuf[0] != ID_P_DATA) bu_exit(1, "mis-count of Q records?\n");
+
+ /* Input always has 5 points, even if all aren't significant */
+ fp->verts = (fastf_t *)bu_malloc(5*3*sizeof(fastf_t), "verts[]");
+ fp->norms = (fastf_t *)bu_malloc(5*3*sizeof(fastf_t), "norms[]");
+
+ cp = ibuf;
+ cp++; /* ident */
+ cp = nxt_spc(cp); /* skip the space */
+
+ fp->npts = (char)atoi(cp);
+ CLAMP(pg->max_npts, fp->npts, pg->npoly * 3);
+
+ for (i = 0; i < 5*3; i++) {
+ cp = nxt_spc(cp);
+ fp->verts[i] = atof(cp);
+ }
+
+ for (i = 0; i < 5*3; i++) {
+ cp = nxt_spc(cp);
+ fp->norms[i] = atof(cp);
+ }
+ }
+
+ /* Convert the polysolid to a BoT */
+ RT_DB_INTERNAL_INIT(&intern);
+ intern.idb_major_type = DB5_MAJORTYPE_BRLCAD;
+ intern.idb_type = ID_POLY;
+ intern.idb_meth = &OBJ[ID_POLY];
+ intern.idb_ptr = pg;
+
+ /* this tolerance structure is only used for converting polysolids
+ * to BOT's use zero distance to avoid losing any polysolid facets
+ */
+ tol.magic = BN_TOL_MAGIC;
+ tol.dist = 0.0;
+ tol.dist_sq = tol.dist * tol.dist;
+ tol.perp = 1e-6;
+ tol.para = 1 - tol.perp;
+
+ if (rt_pg_to_bot(&intern, &tol, &rt_uniresource) < 0)
+ bu_exit(1, "Failed to convert [%s] polysolid object to triangle
mesh\n", name);
+ /* The polysolid is freed by the converter */
+
+ /* Since we already have an internal form, this is much simpler
+ * than calling mk_bot().
+ */
+ if (wdb_put_internal(iofp, name, &intern, mk_conv2mm) < 0)
+ bu_exit(1, "Failed to create [%s] triangle mesh representation from
polysolid object\n", name);
+ /* BoT internal has been freed */
+}
+
+
+/**
+ * Add information to the region-id based coloring table.
+ */
+void
+materbld(void)
+{
+ char *cp;
+ int low, hi;
+ int r, g, b;
+
+ cp = ibuf;
+ cp++; /* skip ID_MATERIAL */
+ cp = nxt_spc(cp); /* skip the space */
+
+ cp = nxt_spc(cp);
+ low = (short)atoi(cp);
+ cp = nxt_spc(cp);
+ hi = (short)atoi(cp);
+ cp = nxt_spc(cp);
+ r = (unsigned char)atoi(cp);
+ cp = nxt_spc(cp);
+ g = (unsigned char)atoi(cp);
+ cp = nxt_spc(cp);
+ b = (unsigned char)atoi(cp);
+
+ /* Put it on a linked list for output later */
+ rt_color_addrec(low, hi, r, g, b, -1L);
+}
+
+
+void
+clinebld(void)
+{
+ char my_name[NAME_LEN];
+ fastf_t thickness;
+ fastf_t radius;
+ point_t V;
+ vect_t height;
+ char *cp;
+ char *np;
+
+ cp = ibuf;
+ cp++;
+ cp = nxt_spc(cp);
+
+ np = my_name;
+ while (*cp != ' ' && *cp != '\n' && *cp != '\r') {
+ *np++ = *cp++;
+ }
+ *np = '\0';
+
+ cp = nxt_spc(cp);
+ V[0] = atof(cp);
+ cp = nxt_spc(cp);
+ V[1] = atof(cp);
+ cp = nxt_spc(cp);
+ V[2] = atof(cp);
+ cp = nxt_spc(cp);
+ height[0] = atof(cp);
+ cp = nxt_spc(cp);
+ height[1] = atof(cp);
+ cp = nxt_spc(cp);
+ height[2] = atof(cp);
+ cp = nxt_spc(cp);
+ radius = atof(cp);
+ cp = nxt_spc(cp);
+ thickness = atof(cp);
+ mk_cline(iofp, my_name, V, height, radius, thickness);
+}
+
+
+void
+botbld(void)
+{
+ char my_name[NAME_LEN];
+ char type;
+ int mode, orientation, error_mode;
+ unsigned long int num_vertices, num_faces;
+ unsigned long int i, j;
+ double a[3];
+ fastf_t *vertices;
+ fastf_t *thick=NULL;
+ int *faces;
+ struct bu_bitv *facemode=NULL;
+
+ sscanf(ibuf, "%c %200s %d %d %d %lu %lu", &type, my_name, &mode,
&orientation, /* NAME_LEN */
+ &error_mode, &num_vertices, &num_faces);
+
+ /* get vertices */
+ vertices = (fastf_t *)bu_calloc(num_vertices * 3, sizeof(fastf_t),
"botbld: vertices");
+ for (i=0; i<num_vertices; i++) {
+ bu_fgets(ibuf, BUFSIZE, iifp);
+ sscanf(ibuf, "%lu: %le %le %le", &j, &a[0], &a[1], &a[2]);
+ if (i != j) {
+ bu_log("Vertices out of order in solid %s (expecting %lu, found
%lu)\n",
+ my_name, i, j);
+ bu_free((char *)vertices, "botbld: vertices");
+ bu_log("Skipping this solid!\n");
+ while (ibuf[0] == '\t')
+ bu_fgets(ibuf, BUFSIZE, iifp);
+ return;
+ }
+ VMOVE(&vertices[i*3], a);
+ }
+
+ /* get faces (and possibly thicknesses */
+ faces = (int *)bu_calloc(num_faces * 3, sizeof(int), "botbld: faces");
+ if (mode == RT_BOT_PLATE)
+ thick = (fastf_t *)bu_calloc(num_faces, sizeof(fastf_t), "botbld
thick");
+ for (i=0; i<num_faces; i++) {
+ bu_fgets(ibuf, BUFSIZE, iifp);
+ if (mode == RT_BOT_PLATE)
+ sscanf(ibuf, "%lu: %d %d %d %le", &j, &faces[i*3], &faces[i*3+1],
&faces[i*3+2], &a[0]);
+ else
+ sscanf(ibuf, "%lu: %d %d %d", &j, &faces[i*3], &faces[i*3+1],
&faces[i*3+2]);
+
+ if (i != j) {
+ bu_log("Faces out of order in solid %s (expecting %lu, found
%lu)\n",
+ my_name, i, j);
+ bu_free((char *)vertices, "botbld: vertices");
+ bu_free((char *)faces, "botbld: faces");
+ if (mode == RT_BOT_PLATE)
+ bu_free((char *)thick, "botbld thick");
+ bu_log("Skipping this solid!\n");
+ while (ibuf[0] == '\t')
+ bu_fgets(ibuf, BUFSIZE, iifp);
+ return;
+ }
+
+ if (mode == RT_BOT_PLATE)
+ thick[i] = a[0];
+ }
+
+ if (mode == RT_BOT_PLATE) {
+ /* get bit vector */
+ bu_fgets(ibuf, BUFSIZE, iifp);
+ facemode = bu_hex_to_bitv(&ibuf[1]);
+ }
+
+ mk_bot(iofp, my_name, mode, orientation, 0, num_vertices, num_faces,
+ vertices, faces, thick, facemode);
+
+ bu_free((char *)vertices, "botbld: vertices");
+ bu_free((char *)faces, "botbld: faces");
+ if (mode == RT_BOT_PLATE) {
+ bu_free((char *)thick, "botbld thick");
+ bu_free((char *)facemode, "botbld facemode");
+ }
+}
+
+
+/**
+ * This routine reads pipe data from standard in, constructs a
+ * doubly linked list of pipe points, and sends this list to
+ * mk_pipe().
+ */
+void
+pipebld(void)
+{
+
+ char name[NAME_LEN];
+ char *cp;
+ char *np;
+ struct wdb_pipe_pnt *sp;
+ struct bu_list head;
+
+ /* Process the first ibuffer */
+
+ cp = ibuf;
+ cp++; /* ident, not used later */
+ cp = nxt_spc(cp); /* skip spaces */
+
+ np = name;
+ while (*cp != '\n' && *cp != '\r' && *cp != '\0') {
+ *np++ = *cp++;
+ }
+ *np = '\0'; /* null terminate the string */
+
+
+ /* Read data lines and process */
+
+ BU_LIST_INIT(&head);
+ bu_fgets(ibuf, BUFSIZE, iifp);
+ while (bu_strncmp (ibuf, "END_PIPE", 8)) {
+ double id, od, x, y, z, bendradius;
+
+ BU_ALLOC(sp, struct wdb_pipe_pnt);
+
+ sscanf(ibuf, "%le %le %le %le %le %le",
+ &id, &od,
+ &bendradius, &x, &y, &z);
+
+ sp->l.magic = WDB_PIPESEG_MAGIC;
+
+ sp->pp_id = id;
+ sp->pp_od = od;
+ sp->pp_bendradius = bendradius;
+ VSET(sp->pp_coord, x, y, z);
+
+ BU_LIST_INSERT(&head, &sp->l);
+ bu_fgets(ibuf, BUFSIZE, iifp);
+ }
+
+ mk_pipe(iofp, name, &head);
+ mk_pipe_free(&head);
+}
+
+
+/**
+ * This routine reads particle data from standard in, and constructs
+ * the parameters required by mk_particle.
+ */
+void
+particlebld(void)
+{
+
+ char name[NAME_LEN];
+ char ident;
+ point_t vertex;
+ vect_t height;
+ double vrad;
+ double hrad;
+ double scanvertex[3];
+ double scanheight[3];
+
+
+ /* Read all the information out of the existing ibuffer. Note that
+ * particles fit into one granule.
+ */
+
+ sscanf(ibuf, "%c %200s %le %le %le %le %le %le %le %le", /* NAME_LEN */
+ &ident, name,
+ &scanvertex[0],
+ &scanvertex[1],
+ &scanvertex[2],
+ &scanheight[0],
+ &scanheight[1],
+ &scanheight[2],
+ &vrad, &hrad);
+ /* convert double to fastf_t */
+ VMOVE(vertex, scanvertex);
+ VMOVE(height, scanheight);
+
+ mk_particle(iofp, name, vertex, height, vrad, hrad);
+}
+
+
+/**
+ * This routine reads arbn data from standard in and sends it to
+ * mk_arbn().
+ */
+void
+arbnbld(void)
+{
+
+ char name[NAME_LEN] = {0};
+ char type[TYPE_LEN] = {0};
+ int i;
+ int neqn; /* number of eqn expected */
+ plane_t *eqn; /* pointer to plane equations for faces */
+ char *cp;
+ char *np;
+
+ /* Process the first ibuffer */
+
+ cp = ibuf;
+ cp++; /* ident */
+ cp = nxt_spc(cp); /* skip spaces */
+
+ np = name;
+ while (*cp != ' ') {
+ *np++ = *cp++;
+ }
+ *np = '\0'; /* null terminate the string */
+
+ cp = nxt_spc(cp);
+
+ neqn = atoi(cp); /* find number of eqns */
+
+ /* Check to make sure plane equations actually came in. */
+ if (neqn <= 0) {
+ bu_log("asc2g: warning: %d equations counted for arbn %s\n", neqn,
name);
+ }
+
+ /* Malloc space for the in-coming plane equations */
+ eqn = (plane_t *)bu_malloc(neqn * sizeof(plane_t), "eqn");
+
+ /* Now, read the plane equations and put in appropriate place */
+
+ for (i = 0; i < neqn; i++) {
+ double scan[4];
+
+ bu_fgets(ibuf, BUFSIZE, iifp);
+ sscanf(ibuf, "%200s %le %le %le %le", type, /* TYPE_LEN */
+ &scan[0], &scan[1], &scan[2], &scan[3]);
+ /* convert double to fastf_t */
+ HMOVE(eqn[i], scan);
+ }
+
+ mk_arbn(iofp, name, neqn, (const plane_t *)eqn);
+
+ bu_free(eqn, "eqn");
+}
+
+
+/**
+ * This routine checks the last character in the string to see if it matches
the
+ * specified character. Used by gettclblock() to check for an escaped return.
+ *
+ */
+int
+endswith(char *line, char ch)
+{
+ if (*(line+strlen(line)-1) == ch) {
+ return 1;
+ }
+ return 0;
+}
+/**
+ * This routine counts the number of open braces and is used to determine
whether a Tcl
+ * command is complete.
+ *
+ */
+int
+bracecnt(char *line)
+{
+ char *start;
+ int cnt = 0;
+
+ start = line;
+ while (*start != '\0') {
+ if (*start == '{') {
+ cnt++;
+ } else if (*start == '}') {
+ cnt--;
+ }
+ start++;
+ }
+ return cnt;
+}
+/**
+ * This routine reads the next block of Tcl commands. This block is expected
to be a Tcl
+ * command script and will be fed to an interpreter using Tcl_Eval(). Any
escaped returns
+ * or open braces are parsed through and concatenated ensuring Tcl commands
are complete.
+ *
+ * SIZE is used as the approximate blocking size allowing to grow past this to
close the
+ * command line.
+ */
+int
+gettclblock(struct bu_vls *line, FILE *fp)
+{
+ int ret = 0;
+ struct bu_vls tmp = BU_VLS_INIT_ZERO;
+
+ if ((ret=bu_vls_gets(line, fp)) >= 0) {
+ int bcnt = 0;
+ int escapedcr = 0;
+
+ linecnt++;
+ escapedcr = endswith(bu_vls_addr(line), '\\');
+ bcnt = bracecnt(bu_vls_addr(line));
+ while ((ret >= 0) && ((bu_vls_strlen(line) < SIZE) || (escapedcr) ||
(bcnt != 0))) {
+ linecnt++;
+ if (escapedcr) {
+ bu_vls_trunc(line, bu_vls_strlen(line)-1);
+ }
+ if ((ret=bu_vls_gets(&tmp, fp)) > 0) {
+ escapedcr = endswith(bu_vls_addr(&tmp), '\\');
+ bcnt = bcnt + bracecnt(bu_vls_addr(&tmp));
+ bu_vls_putc(line, '\n');
+ bu_vls_strcat(line, bu_vls_addr(&tmp));
+ bu_vls_trunc(&tmp, 0);
+ } else {
+ escapedcr = 0;
+ }
+ }
+ ret = (int)bu_vls_strlen(line);
+ }
+ bu_vls_free(&tmp);
+
+ return ret;
+}
+
+/*******************************************************************/
+/* Main asc V4 read entry point */
+/*******************************************************************/
+int
asc_read_v4(
struct gcv_context *UNUSED(c),
const struct gcv_opts *UNUSED(o),
@@ -49,6 +1495,120 @@
while (std::getline(fs, sline)) {
std::cout << sline << "\n";
}
+
+ /* allocate our input buffer */
+ ibuf = (char *)bu_calloc(sizeof(char), BUFSIZE, "input buffer");
+
+ /* Read ASCII input file, each record on a line */
+ while ((bu_fgets(ibuf, BUFSIZE, iifp)) != (char *)0) {
+
+ after_read:
+ /* Clear the output record -- vital! */
+ (void)memset((char *)&irecord, 0, sizeof(record));
+
+ /* Check record type */
+ switch (ibuf[0]) {
+ case ID_SOLID:
+ solbld();
+ continue;
+
+ case ID_COMB:
+ if (combbld() > 0) goto after_read;
+ continue;
+
+ case ID_MEMB:
+ bu_log("Warning: unattached Member record, ignored\n");
+ continue;
+
+ case ID_ARS_A:
+ arsabld();
+ continue;
+
+ case ID_ARS_B:
+ arsbbld();
+ continue;
+
+ case ID_P_HEAD:
+ polyhbld();
+ continue;
+
+ case ID_P_DATA:
+ bu_log("Unattached POLY-solid P_DATA (Q) record, skipping\n");
+ continue;
+
+ case ID_IDENT:
+ identbld();
+ continue;
+
+ case ID_MATERIAL:
+ materbld();
+ continue;
+
+ case ID_BSOLID:
+ bu_log("WARNING: conversion support for old B-spline solid
geometry is not supported. Contact [email protected] if you need this feature.");
+ continue;
+
+ case ID_BSURF:
+ bu_log("WARNING: conversion support for old B-spline surface
geometry is not supported. contact [email protected] if you need this feature.");
+ continue;
+
+ case DBID_PIPE:
+ pipebld();
+ continue;
+
+ case DBID_STRSOL:
+ strsolbld();
+ continue;
+
+ case DBID_NMG:
+ nmgbld();
+ continue;
+
+ case DBID_PARTICLE:
+ particlebld();
+ continue;
+
+ case DBID_ARBN:
+ arbnbld();
+ continue;
+
+ case DBID_CLINE:
+ clinebld();
+ continue;
+
+ case DBID_BOT:
+ botbld();
+ continue;
+
+ case DBID_EXTR:
+ extrbld();
+ continue;
+
+ case DBID_SKETCH:
+ sktbld();
+ continue;
+
+ case '#':
+ continue;
+
+ default:
+ bu_log("asc2g: bad record type '%c' (0%o), skipping\n",
ibuf[0], ibuf[0]);
+ bu_log("%s\n", ibuf);
+ continue;
+ }
+ }
+
+ /* Now, at the end of the database, dump out the entire
+ * region-id-based color table.
+ */
+ mk_write_color_table(iofp);
+
+ /* close up shop */
+ bu_free(ibuf, "input buffer");
+ ibuf = NULL; /* sanity */
+ fclose(iifp); iifp = NULL;
+ wdb_close(iofp); iofp = NULL;
+
return 1;
}
Modified: brlcad/trunk/src/libgcv/plugins/asc/asc_v5.cpp
===================================================================
--- brlcad/trunk/src/libgcv/plugins/asc/asc_v5.cpp 2020-07-09 16:15:58 UTC
(rev 76288)
+++ brlcad/trunk/src/libgcv/plugins/asc/asc_v5.cpp 2020-07-09 17:15:22 UTC
(rev 76289)
@@ -37,6 +37,99 @@
#include "gcv/api.h"
#include "gcv/util.h"
+#if 0
+
+// TODO:
+// This is the asc2g code that uses libtclcad
+// to read in v5 asc files as Tcl scripts.
+// It needs to be replaced with a non-Tcl based
+// parsing code that reads what g2asc writes.
+
+char *aliases[] = {
+ "attr",
+ "color",
+ "put",
+ "title",
+ "units",
+ "find",
+ "dbfind",
+ "rm",
+ (char *)0
+};
+
+Tcl_Interp *interp;
+Tcl_Interp *safe_interp;
+
+/* this is a Tcl script */
+
+rewind(ifp);
+bu_vls_trunc(&line, 0);
+BU_LIST_INIT(&RTG.rtg_headwdb.l);
+
+interp = Tcl_CreateInterp();
+Go_Init(interp);
+wdb_close(ofp);
+
+{
+ int ac = 4;
+ const char *av[5];
+
+ av[0] = "to_open";
+ av[1] = db_name;
+ av[2] = "db";
+ av[3] = argv[2];
+ av[4] = (char *)0;
+
+ if (to_open_tcl((ClientData)0, interp, ac, av) != TCL_OK) {
+ fclose(ifp);
+ bu_log("Failed to initialize tclcad_obj!\n");
+ Tcl_Exit(1);
+ }
+}
+
+/* Create the safe interpreter */
+if ((safe_interp = Tcl_CreateSlave(interp, slave_name, 1)) == NULL) {
+ fclose(ifp);
+ bu_log("Failed to create safe interpreter");
+ Tcl_Exit(1);
+}
+
+/* Create aliases */
+{
+ int i;
+ int ac = 1;
+ const char *av[2];
+
+ av[1] = (char *)0;
+ for (i = 0; aliases[i] != (char *)0; ++i) {
+ av[0] = aliases[i];
+ Tcl_CreateAlias(safe_interp, aliases[i], interp, db_name, ac, av);
+ }
+ /* add "find" separately */
+ av[0] = "dbfind";
+ Tcl_CreateAlias(safe_interp, "find", interp, db_name, ac, av);
+}
+
+while ((gettclblock(&line, ifp)) >= 0) {
+ if (Tcl_Eval(safe_interp, (const char *)bu_vls_addr(&line)) != TCL_OK) {
+ fclose(ifp);
+ bu_log("Failed to process input file (%s)!\n", argv[1]);
+ bu_log("%s\n", Tcl_GetStringResult(safe_interp));
+ Tcl_Exit(1);
+ }
+ bu_vls_trunc(&line, 0);
+}
+
+/* free up our resources */
+bu_vls_free(&line);
+bu_vls_free(&str_title);
+bu_vls_free(&str_put);
+
+fclose(ifp);
+
+Tcl_Exit(0);
+#endif
+
int
asc_read_v5(
struct gcv_context *UNUSED(c),
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