Revision: 76285
http://sourceforge.net/p/brlcad/code/76285
Author: starseeker
Date: 2020-07-08 16:18:01 +0000 (Wed, 08 Jul 2020)
Log Message:
-----------
Pull the g2asc logic from g2asc.c and rough it into the respective gcv plugin
files. Not working or close to it - just figuring out which pieces belong
where. For v5, once we know what we're writing out we'll know what we need to
read in - anything added to a .asc file not written by g2asc will promote an
asc file to an all-up Tcl script needing the full libtclcad logic to evaluate.
Modified Paths:
--------------
brlcad/trunk/src/libgcv/plugins/asc/asc.cpp
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.cpp
===================================================================
--- brlcad/trunk/src/libgcv/plugins/asc/asc.cpp 2020-07-08 15:09:29 UTC (rev
76284)
+++ brlcad/trunk/src/libgcv/plugins/asc/asc.cpp 2020-07-08 16:18:01 UTC (rev
76285)
@@ -37,6 +37,7 @@
extern void asc_read_v4(struct gcv_context *c, const struct gcv_opts *o,
std::ifstream &fs);
extern void asc_read_v5(struct gcv_context *c, const struct gcv_opts *o,
std::ifstream &fs);
+extern void asc_write_v5(struct gcv_context *c, const struct gcv_opts *o,
const char *dest_path);
static int
asc_can_read(const char *data)
@@ -111,11 +112,13 @@
}
static int
-asc_write(struct gcv_context *context, const struct gcv_opts *gcv_options,
- const void *UNUSED(options_data), const char *dest_path)
+asc_write(struct gcv_context *c, const struct gcv_opts *o,
+ const void *UNUSED(odata), const char *dest_path)
{
- if (!context || !gcv_options || !dest_path) return 0;
+ if (!c || !o || !dest_path) return 0;
bu_log("asc write\n");
+ // TODO - check for version option
+ asc_write_v5(c, o, dest_path);
return 1;
}
Modified: brlcad/trunk/src/libgcv/plugins/asc/asc_v4.cpp
===================================================================
--- brlcad/trunk/src/libgcv/plugins/asc/asc_v4.cpp 2020-07-08 15:09:29 UTC
(rev 76284)
+++ brlcad/trunk/src/libgcv/plugins/asc/asc_v4.cpp 2020-07-08 16:18:01 UTC
(rev 76285)
@@ -32,6 +32,8 @@
#include <sstream>
#include <string>
+#include "rt/db4.h"
+#include "raytrace.h"
#include "gcv/api.h"
#include "gcv/util.h"
@@ -48,9 +50,980 @@
std::cout << sline << "\n";
}
return 1;
+}
+static int combdump(void);
+static void idendump(void), polyhead_asc(void), polydata_asc(void);
+static void soldump(void), extrdump(void), sketchdump(void);
+static void membdump(union record *rp), arsadump(void), arsbdump(void);
+static void materdump(void), bspldump(void), bsurfdump(void);
+static void pipe_dump(void), particle_dump(void), dump_pipe_segs(char *,
struct bu_list *);
+static void arbn_dump(void), cline_dump(void), bot_dump(void);
+static void nmg_dump(void);
+static void strsol_dump(void);
+static char * strchop(char *str, size_t len);
+
+const mat_t id_mat = MAT_INIT_IDN; /* identity matrix for pipes */
+#define CH(x) strchop(x, sizeof(x))
+union record record; /* GED database record */
+FILE *ifp;
+FILE *ofp;
+
+/*
+ * Take a database name and null-terminate it,
+ * converting unprintable characters to something printable.
+ * Here we deal with names not being null-terminated.
+ */
+static char *
+encode_name(char *str)
+{
+ static char buf[NAMESIZE+1];
+ char *ip = str;
+ char *op = buf;
+ int warn = 0;
+
+ while (op < &buf[NAMESIZE]) {
+ if (*ip == '\0') break;
+ if (isprint((int)*ip) && !isspace((int)*ip)) {
+ *op++ = *ip++;
+ } else {
+ *op++ = '@';
+ ip++;
+ warn = 1;
+ }
+ }
+ *op = '\0';
+ if (warn) {
+ fprintf(stderr,
+ "g2asc: Illegal char in object name, converted to '%s'\n",
+ buf);
+ }
+ if (op == buf) {
+ /* Null input name */
+ fprintf(stderr,
+ "g2asc: NULL object name converted to -=NULL=-\n");
+
+ // TODO
+ // return "-=NULL=-";
+ return NULL;
+ }
+ return buf;
}
+
+/*
+ * Take "ngran" granules, and put them in memory.
+ * The first granule comes from the global extern "record",
+ * the remainder are read from ifp.
+ */
+static void
+get_ext(struct bu_external *ep, size_t ngran)
+{
+ size_t count;
+
+ BU_EXTERNAL_INIT(ep);
+
+ ep->ext_nbytes = ngran * sizeof(union record);
+ ep->ext_buf = (uint8_t *)bu_malloc(ep->ext_nbytes, "get_ext ext_buf");
+
+ /* Copy the freebie (first) record into the array of records. */
+ memcpy((char *)ep->ext_buf, (char *)&record, sizeof(union record));
+ if (ngran <= 1) return;
+
+ count = fread(((char *)ep->ext_buf)+sizeof(union record),
+ sizeof(union record), ngran-1, ifp);
+ if (count != (size_t)ngran-1) {
+ fprintf(stderr,
+ "g2asc: get_ext: wanted to read %lu granules, got %lu\n",
+ (unsigned long)ngran-1, (unsigned long)count);
+ bu_exit(1, NULL);
+ }
+}
+
+static void
+nmg_dump(void)
+{
+ union record rec;
+ long struct_count[26];
+ size_t i, granules;
+ size_t j, k;
+
+ /* just in case someone changes the record size */
+ if (sizeof(union record)%32)
+ {
+ fprintf(stderr, "g2asc: nmg_dump cannot work with records not multiple
of 32\n");
+ bu_exit(-1, NULL);
+ }
+
+ /* get number of granules needed for this NMG */
+ granules = ntohl(*(uint32_t *)record.nmg.N_count);
+
+ /* get the array of structure counts */
+ for (j = 0; j < 26; j++)
+ struct_count[j] = ntohl(*(uint32_t *)&record.nmg.N_structs[j*4]);
+
+ /* output some header info */
+ fprintf(ofp, "%c %d %.16s %lu\n",
+ record.nmg.N_id, /* N */
+ record.nmg.N_version, /* NMG version */
+ record.nmg.N_name, /* solid name */
+ (unsigned long)granules); /* number of additional
granules */
+
+ /* output the structure counts */
+ for (j = 0; j < 26; j++)
+ fprintf(ofp, " %ld", struct_count[j]);
+ (void)fputc('\n', ofp);
+
+ /* dump the reminder in hex format */
+ for (i = 0; i < granules; i++) {
+ char *cp;
+ /* Read the record */
+ if (!fread((char *)&rec, sizeof record, 1, ifp)) {
+ fprintf(stderr, "Error reading nmg granules\n");
+ bu_exit(-1, NULL);
+ }
+ cp = (char *)&rec;
+
+ /* 32 bytes per line */
+ for (k = 0; k < sizeof(union record)/32; k++) {
+ for (j = 0; j < 32; j++)
+ fprintf(ofp, "%02x", (0xff & (*cp++))); /* two hex
digits per byte */
+ fputc('\n', ofp);
+ }
+ }
+}
+
+static void
+strsol_dump(void) /* print out strsol solid info */
+{
+ union record rec[DB_SS_NGRAN];
+ char *cp;
+
+ /* get all the strsol granules */
+ rec[0] = record; /* struct copy the current record */
+
+ /* read the rest from ifp */
+ if (!fread((char *)&rec[1], sizeof record, DB_SS_NGRAN-1, ifp))
+ {
+ fprintf(stderr, "Error reading strsol granules\n");
+ bu_exit(-1, NULL);
+ }
+
+ /* make sure that at least the last byte is null */
+ cp = (char *)&rec[DB_SS_NGRAN-1];
+ cp += (sizeof(union record) - 1);
+ *cp = '\0';
+
+ fprintf(ofp, "%c %.16s %.16s %s\n",
+ rec[0].ss.ss_id, /* s */
+ rec[0].ss.ss_keyword, /* "ebm", "vol", or ??? */
+ rec[0].ss.ss_name, /* solid name */
+ rec[0].ss.ss_args); /* everything else */
+
+}
+
+static void
+idendump(void) /* Print out Ident record information */
+{
+ fprintf(ofp, "%c %d %.6s\n",
+ record.i.i_id, /* I */
+ record.i.i_units, /* units */
+ CH(record.i.i_version) /* version */
+ );
+ fprintf(ofp, "%.72s\n",
+ CH(record.i.i_title) /* title or description */
+ );
+
+ /* Print a warning message on stderr if versions differ */
+ if (!BU_STR_EQUAL(record.i.i_version, ID_VERSION)) {
+ fprintf(stderr,
+ "g2asc: File is version (%s), Program is version (%s)\n",
+ record.i.i_version, ID_VERSION);
+ }
+}
+
+static void
+polyhead_asc(void) /* Print out Polyhead record information */
+{
+ fprintf(ofp, "%c ", record.p.p_id); /* P */
+ fprintf(ofp, "%.16s", encode_name(record.p.p_name)); /* unique name
*/
+ fprintf(ofp, "\n"); /* Terminate w/ a newline */
+}
+
+static void
+polydata_asc(void) /* Print out Polydata record information */
+{
+ int i, j;
+
+ fprintf(ofp, "%c ", record.q.q_id); /* Q */
+ fprintf(ofp, "%d", record.q.q_count); /* # of vertices <= 5 */
+ for (i = 0; i < 5; i++) {
+ /* [5][3] vertices */
+ for (j = 0; j < 3; j++) {
+ fprintf(ofp, " %.12e", record.q.q_verts[i][j]);
+ }
+ }
+ for (i = 0; i < 5; i++) {
+ /* [5][3] normals */
+ for (j = 0; j < 3; j++) {
+ fprintf(ofp, " %.12e", record.q.q_norms[i][j]);
+ }
+ }
+ fprintf(ofp, "\n"); /* Terminate w/ a newline */
+}
+
+static void
+soldump(void) /* Print out Solid record information */
+{
+ int i;
+
+ fprintf(ofp, "%c ", record.s.s_id); /* S */
+ fprintf(ofp, "%d ", record.s.s_type); /* GED primitive type */
+ fprintf(ofp, "%.16s ", encode_name(record.s.s_name)); /* unique name
*/
+ fprintf(ofp, "%d", record.s.s_cgtype);/* COMGEOM solid type */
+ for (i = 0; i < 24; i++)
+ fprintf(ofp, " %.12e", record.s.s_values[i]); /* parameters */
+ fprintf(ofp, "\n"); /* Terminate w/ a newline */
+}
+
+static void
+cline_dump(void)
+{
+ size_t ngranules; /* number of granules, total */
+ char *name;
+ struct rt_cline_internal *cli;
+ struct bu_external ext;
+ struct rt_db_internal intern;
+
+ name = record.cli.cli_name;
+
+ ngranules = 1;
+ get_ext(&ext, ngranules);
+
+ /* Hand off to librt's import() routine */
+ RT_DB_INTERNAL_INIT(&intern);
+ if ((OBJ[ID_CLINE].ft_import4(&intern, &ext, id_mat, DBI_NULL,
&rt_uniresource)) != 0) {
+ fprintf(stderr, "g2asc: cline import failure\n");
+ bu_exit(-1, NULL);
+ }
+
+ cli = (struct rt_cline_internal *)intern.idb_ptr;
+ RT_CLINE_CK_MAGIC(cli);
+
+ fprintf(ofp, "%c ", DBID_CLINE); /* c */
+ fprintf(ofp, "%.16s ", name); /* unique name */
+ fprintf(ofp, "%26.20e %26.20e %26.20e ", V3ARGS(cli->v));
+ fprintf(ofp, "%26.20e %26.20e %26.20e ", V3ARGS(cli->h));
+ fprintf(ofp, "%26.20e %26.20e", cli->radius, cli->thickness);
+ fprintf(ofp, "\n"); /* Terminate w/ a newline */
+
+ rt_db_free_internal(&intern);
+ bu_free_external(&ext);
+}
+
+static void
+bot_dump(void)
+{
+ size_t ngranules;
+ char *name;
+ struct rt_bot_internal *bot;
+ struct bu_external ext;
+ struct rt_db_internal intern;
+ size_t i;
+
+ name = record.bot.bot_name;
+ ngranules = ntohl(*(uint32_t *)record.bot.bot_nrec) + 1;
+ get_ext(&ext, ngranules);
+
+ /* Hand off to librt's import() routine */
+ RT_DB_INTERNAL_INIT(&intern);
+ if ((OBJ[ID_BOT].ft_import4(&intern, &ext, id_mat, DBI_NULL,
&rt_uniresource)) != 0) {
+ fprintf(stderr, "g2asc: bot import failure\n");
+ bu_exit(-1, NULL);
+ }
+
+ bot = (struct rt_bot_internal *)intern.idb_ptr;
+ RT_BOT_CK_MAGIC(bot);
+
+ fprintf(ofp, "%c ", DBID_BOT); /* t */
+ fprintf(ofp, "%.16s ", name); /* unique name */
+ fprintf(ofp, "%d ", bot->mode);
+ fprintf(ofp, "%d ", bot->orientation);
+ fprintf(ofp, "%d ", 0); /* was error_mode */
+ fprintf(ofp, "%lu ", (unsigned long)bot->num_vertices);
+ fprintf(ofp, "%lu", (unsigned long)bot->num_faces);
+ fprintf(ofp, "\n");
+
+ for (i = 0; i < bot->num_vertices; i++)
+ fprintf(ofp, " %lu: %26.20e %26.20e %26.20e\n", (unsigned long)i,
V3ARGS(&bot->vertices[i*3]));
+ if (bot->mode == RT_BOT_PLATE) {
+ struct bu_vls vls = BU_VLS_INIT_ZERO;
+
+ for (i = 0; i < bot->num_faces; i++)
+ fprintf(ofp, " %lu: %d %d %d %26.20e\n", (unsigned long)i,
V3ARGS(&bot->faces[i*3]), bot->thickness[i]);
+ bu_bitv_to_hex(&vls, bot->face_mode);
+ fprintf(ofp, " %s\n", bu_vls_addr(&vls));
+ bu_vls_free(&vls);
+ } else {
+ for (i = 0; i < bot->num_faces; i++)
+ fprintf(ofp, " %lu: %d %d %d\n", (unsigned long)i,
V3ARGS(&bot->faces[i*3]));
+ }
+
+ rt_db_free_internal(&intern);
+ bu_free_external(&ext);
+}
+
+static void
+pipe_dump(void) /* Print out Pipe record information */
+{
+
+ size_t ngranules; /* number of granules, total */
+ char *name;
+ struct rt_pipe_internal *pipeip; /* want a struct for the head,
not a ptr. */
+ struct bu_external ext;
+ struct rt_db_internal intern;
+
+ ngranules = ntohl(*(uint32_t *)record.pwr.pwr_count) + 1;
+ name = record.pwr.pwr_name;
+
+ get_ext(&ext, ngranules);
+
+ /* Hand off to librt's import() routine */
+ RT_DB_INTERNAL_INIT(&intern);
+ if ((OBJ[ID_PIPE].ft_import4(&intern, &ext, id_mat, NULL,
&rt_uniresource)) != 0) {
+ fprintf(stderr, "g2asc: pipe import failure\n");
+ bu_exit(-1, NULL);
+ }
+
+ pipeip = (struct rt_pipe_internal *)intern.idb_ptr;
+ RT_PIPE_CK_MAGIC(pipeip);
+
+ /* send the doubly linked list off to dump_pipe_segs(), which
+ * will print all the information.
+ */
+
+ dump_pipe_segs(name, &pipeip->pipe_segs_head);
+
+ rt_db_free_internal(&intern);
+ bu_free_external(&ext);
+}
+
+static void
+dump_pipe_segs(char *name, struct bu_list *headp)
+{
+
+ struct wdb_pipe_pnt *sp;
+
+ fprintf(ofp, "%c %.16s\n", DBID_PIPE, name);
+
+ /* print parameters for each point: one point per line */
+
+ for (BU_LIST_FOR(sp, wdb_pipe_pnt, headp)) {
+ fprintf(ofp, "%26.20e %26.20e %26.20e %26.20e %26.20e %26.20e\n",
+ sp->pp_id, sp->pp_od, sp->pp_bendradius, V3ARGS(sp->pp_coord));
+ }
+ fprintf(ofp, "END_PIPE %s\n", name);
+}
+
+/*
+ * Print out Particle record information.
+ * Note that particles fit into one granule only.
+ */
+static void
+particle_dump(void)
+{
+ struct rt_part_internal *part; /* head for the structure */
+ struct bu_external ext;
+ struct rt_db_internal intern;
+
+ get_ext(&ext, 1);
+
+ /* Hand off to librt's import() routine */
+ RT_DB_INTERNAL_INIT(&intern);
+ if ((OBJ[ID_PARTICLE].ft_import4(&intern, &ext, id_mat, NULL,
&rt_uniresource)) != 0) {
+ fprintf(stderr, "g2asc: particle import failure\n");
+ bu_exit(-1, NULL);
+ }
+
+ part = (struct rt_part_internal *)intern.idb_ptr;
+ RT_PART_CK_MAGIC(part);
+
+ /* Particle type is picked up on here merely to ensure receiving
+ * valid data. The type is not used any further.
+ */
+
+ switch (part->part_type) {
+ case RT_PARTICLE_TYPE_SPHERE:
+ break;
+ case RT_PARTICLE_TYPE_CYLINDER:
+ break;
+ case RT_PARTICLE_TYPE_CONE:
+ break;
+ default:
+ fprintf(stderr, "g2asc: no particle type %d\n", part->part_type);
+ bu_exit(-1, NULL);
+ }
+
+ fprintf(ofp, "%c %.16s %26.20e %26.20e %26.20e %26.20e %26.20e %26.20e
%26.20e %26.20e\n",
+ record.part.p_id, record.part.p_name,
+ part->part_V[X],
+ part->part_V[Y],
+ part->part_V[Z],
+ part->part_H[X],
+ part->part_H[Y],
+ part->part_H[Z],
+ part->part_vrad, part->part_hrad);
+}
+
+
+/*
+ * Print out arbn information.
+ *
+ */
+static void
+arbn_dump(void)
+{
+ size_t ngranules; /* number of granules to be read */
+ size_t i; /* a counter */
+ char *name;
+ struct rt_arbn_internal *arbn;
+ struct bu_external ext;
+ struct rt_db_internal intern;
+
+ ngranules = ntohl(*(uint32_t *)record.n.n_grans) + 1;
+ name = record.n.n_name;
+
+ get_ext(&ext, ngranules);
+
+ /* Hand off to librt's import() routine */
+ RT_DB_INTERNAL_INIT(&intern);
+ if ((OBJ[ID_ARBN].ft_import4(&intern, &ext, id_mat, NULL,
&rt_uniresource)) != 0) {
+ fprintf(stderr, "g2asc: arbn import failure\n");
+ bu_exit(-1, NULL);
+ }
+
+ arbn = (struct rt_arbn_internal *)intern.idb_ptr;
+ RT_ARBN_CK_MAGIC(arbn);
+
+ fprintf(ofp, "%c %.16s %lu\n", 'n', name, (unsigned long)arbn->neqn);
+ for (i = 0; i < arbn->neqn; i++) {
+ fprintf(ofp, "n %26.20e %20.26e %26.20e %26.20e\n",
+ arbn->eqn[i][X], arbn->eqn[i][Y],
+ arbn->eqn[i][Z], arbn->eqn[i][3]);
+ }
+
+ rt_db_free_internal(&intern);
+ bu_free_external(&ext);
+}
+
+
+/*
+ * Note that for compatibility with programs such as FRED that
+ * (inappropriately) read .asc files, the member count has to be
+ * recalculated here.
+ *
+ * Returns -
+ * 0 converted OK
+ * 1 converted OK, left next record in global "record" for reuse.
+ */
+static int
+combdump(void) /* Print out Combination record information */
+{
+ int m1, m2; /* material property flags */
+ struct bu_list head;
+ struct mchain {
+ struct bu_list l;
+ union record r;
+ };
+ struct mchain *mp;
+ struct mchain *ret_mp = (struct mchain *)0;
+ int mcount;
+
+ /*
+ * Gobble up all subsequent member records, so that
+ * an accurate count of them can be output.
+ */
+ BU_LIST_INIT(&head);
+ mcount = 0;
+ while (1) {
+ BU_GET(mp, struct mchain);
+ if (fread((char *)&mp->r, sizeof(mp->r), 1, ifp) != 1
+ || feof(ifp))
+ break;
+ if (mp->r.u_id != ID_MEMB) {
+ ret_mp = mp; /* Handle it later */
+ break;
+ }
+ BU_LIST_INSERT(&head, &(mp->l));
+ mcount++;
+ }
+
+ /*
+ * Output the combination
+ */
+ fprintf(ofp, "%c ", record.c.c_id); /* C */
+ switch (record.c.c_flags) {
+ case DBV4_REGION:
+ fprintf(ofp, "Y "); /* Y if `R' */
+ break;
+ case DBV4_NON_REGION_NULL:
+ case DBV4_NON_REGION:
+ fprintf(ofp, "N "); /* N if ` ' or '\0' */
+ break;
+ case DBV4_REGION_FASTGEN_PLATE:
+ fprintf(ofp, "P ");
+ break;
+ case DBV4_REGION_FASTGEN_VOLUME:
+ fprintf(ofp, "V ");
+ break;
+ }
+ fprintf(ofp, "%.16s ", encode_name(record.c.c_name)); /* unique name
*/
+ fprintf(ofp, "%d ", record.c.c_regionid); /* region ID code */
+ fprintf(ofp, "%d ", record.c.c_aircode); /* air space code */
+
+ /* DEPRECATED: # of members */
+ fprintf(ofp, "%d ", mcount);
+
+ /* DEPRECATED: COMGEOM region # */
+ fprintf(ofp, "%d ", 0 /* was record.c.c_num */);
+
+ fprintf(ofp, "%d ", record.c.c_material); /* material code */
+ fprintf(ofp, "%d ", record.c.c_los); /* equiv. LOS est. */
+ fprintf(ofp, "%d %d %d %d ",
+ record.c.c_override ? 1 : 0,
+ record.c.c_rgb[0],
+ record.c.c_rgb[1],
+ record.c.c_rgb[2]);
+ m1 = m2 = 0;
+ if (isprint((int)record.c.c_matname[0])) {
+ m1 = 1;
+ if (record.c.c_matparm[0])
+ m2 = 1;
+ }
+ fprintf(ofp, "%d %d", m1, m2);
+ switch (record.c.c_inherit) {
+ case DB_INH_HIGHER:
+ fprintf(ofp, " %d", DB_INH_HIGHER);
+ break;
+ default:
+ case DB_INH_LOWER:
+ fprintf(ofp, " %d", DB_INH_LOWER);
+ break;
+ }
+ fprintf(ofp, "\n"); /* Terminate w/ a newline */
+
+ if (m1)
+ fprintf(ofp, "%.32s\n", CH(record.c.c_matname));
+ if (m2)
+ fprintf(ofp, "%.60s\n", CH(record.c.c_matparm));
+
+ /*
+ * Output the member records now
+ */
+ while (BU_LIST_WHILE(mp, mchain, &head)) {
+ membdump(&mp->r);
+ BU_LIST_DEQUEUE(&mp->l);
+ BU_PUT(mp, struct mchain);
+ }
+
+ if (ret_mp) {
+ memcpy((char *)&record, (char *)&ret_mp->r, sizeof(record));
+ BU_PUT(ret_mp, struct mchain);
+ return 1;
+ }
+ return 0;
+}
+
+/*
+ * Print out Member record information.
+ * Intended to be called by combdump only.
+ */
+static void
+membdump(union record *rp)
+{
+ int i;
+
+ fprintf(ofp, "%c ", rp->M.m_id); /* M */
+ fprintf(ofp, "%c ", rp->M.m_relation); /* Boolean oper. */
+ fprintf(ofp, "%.16s ", encode_name(rp->M.m_instname)); /* referred-to
obj. */
+ for (i = 0; i < 16; i++) /* homogeneous transform matrix
*/
+ fprintf(ofp, "%.12e ", rp->M.m_mat[i]);
+ fprintf(ofp, "%d", 0); /* was COMGEOM solid # */
+ fprintf(ofp, "\n"); /* Terminate w/ nl */
+}
+
+static void
+arsadump(void) /* Print out ARS record information */
+{
+ int i;
+ int length; /* Keep track of number of ARS B records */
+
+ fprintf(ofp, "%c ", record.a.a_id); /* A */
+ fprintf(ofp, "%d ", record.a.a_type); /* primitive type */
+ fprintf(ofp, "%.16s ", encode_name(record.a.a_name)); /* unique name
*/
+ fprintf(ofp, "%d ", record.a.a_m); /* # of curves */
+ fprintf(ofp, "%d ", record.a.a_n); /* # of points per curve */
+ fprintf(ofp, "%d ", record.a.a_curlen);/* # of granules per curve */
+ fprintf(ofp, "%d ", record.a.a_totlen);/* # of granules for ARS */
+ fprintf(ofp, "%.12e ", record.a.a_xmax); /* max x coordinate */
+ fprintf(ofp, "%.12e ", record.a.a_xmin); /* min x coordinate */
+ fprintf(ofp, "%.12e ", record.a.a_ymax); /* max y coordinate */
+ fprintf(ofp, "%.12e ", record.a.a_ymin); /* min y coordinate */
+ fprintf(ofp, "%.12e ", record.a.a_zmax); /* max z coordinate */
+ fprintf(ofp, "%.12e", record.a.a_zmin); /* min z coordinate */
+ fprintf(ofp, "\n"); /* Terminate w/ a newline */
+
+ length = (int)record.a.a_totlen; /* Get # of ARS B records */
+
+ for (i = 0; i < length; i++) {
+ arsbdump();
+ }
+}
+
+static void
+arsbdump(void) /* Print out ARS B record information */
+{
+ int i;
+ size_t ret;
+
+ /* Read in a member record for processing */
+ ret = fread((char *)&record, sizeof record, 1, ifp);
+ if (ret != 1)
+ perror("fread");
+ fprintf(ofp, "%c ", record.b.b_id); /* B */
+ fprintf(ofp, "%d ", record.b.b_type); /* primitive type */
+ fprintf(ofp, "%d ", record.b.b_n); /* current curve # */
+ fprintf(ofp, "%d", record.b.b_ngranule); /* current granule */
+ for (i = 0; i < 24; i++) {
+ /* [8*3] vectors */
+ fprintf(ofp, " %.12e", record.b.b_values[i]);
+ }
+ fprintf(ofp, "\n"); /* Terminate w/ a newline */
+}
+
+static void
+materdump(void) /* Print out material description record information */
+{
+ fprintf(ofp, "%c %d %d %d %d %d %d\n",
+ record.md.md_id, /* m */
+ record.md.md_flags, /* UNUSED */
+ record.md.md_low, /* low end of region IDs affected */
+ record.md.md_hi, /* high end of region IDs affected */
+ record.md.md_r,
+ record.md.md_g, /* color of regions: 0..255 */
+ record.md.md_b);
+}
+
+static void
+bspldump(void) /* Print out B-spline solid description record information */
+{
+ fprintf(ofp, "%c %.16s %d\n",
+ record.B.B_id, /* b */
+ encode_name(record.B.B_name), /* unique name */
+ record.B.B_nsurf); /* # of surfaces in this solid */
+}
+
+static void
+bsurfdump(void) /* Print d-spline surface description record
information */
+{
+ size_t i;
+ float *vp;
+ size_t nbytes, count;
+ float *fp;
+
+ fprintf(ofp, "%c %d %d %d %d %d %d %d %d %d\n",
+ record.d.d_id, /* D */
+ record.d.d_order[0], /* order of u and v directions */
+ record.d.d_order[1], /* order of u and v directions */
+ record.d.d_kv_size[0], /* knot vector size (u and v) */
+ record.d.d_kv_size[1], /* knot vector size (u and v) */
+ record.d.d_ctl_size[0], /* control mesh size (u and v)
*/
+ record.d.d_ctl_size[1], /* control mesh size (u and v)
*/
+ record.d.d_geom_type, /* geom type 3 or 4 */
+ record.d.d_nknots, /* # granules of knots */
+ record.d.d_nctls); /* # granules of ctls */
+ /*
+ * The b_surf_head record is followed by
+ * d_nknots granules of knot vectors (first u, then v),
+ * and then by d_nctls granules of control mesh information.
+ * Note that neither of these have an ID field!
+ *
+ * B-spline surface record, followed by
+ * d_kv_size[0] floats,
+ * d_kv_size[1] floats,
+ * padded to d_nknots granules, followed by
+ * ctl_size[0]*ctl_size[1]*geom_type floats,
+ * padded to d_nctls granules.
+ *
+ * IMPORTANT NOTE: granule == sizeof(union record)
+ */
+
+ /* Malloc and clear memory for the KNOT DATA and read it */
+ nbytes = record.d.d_nknots * sizeof(union record);
+ vp = (float *)bu_calloc((unsigned int)nbytes, 1, "KNOT DATA");
+ fp = vp;
+ count = fread((char *)fp, 1, nbytes, ifp);
+ if (count != nbytes) {
+ fprintf(stderr, "g2asc: spline knot read failure\n");
+ bu_exit(1, NULL);
+ }
+ /* Print the knot vector information */
+ count = record.d.d_kv_size[0] + record.d.d_kv_size[1];
+ for (i = 0; i < count; i++) {
+ fprintf(ofp, "%.12e\n", *vp++);
+ }
+ /* Free the knot data memory */
+ (void)bu_free((char *)fp, "KNOT DATA");
+
+ /* Malloc and clear memory for the CONTROL MESH data and read it */
+ nbytes = record.d.d_nctls * sizeof(union record);
+ vp = (float *)bu_calloc((unsigned int)nbytes, 1, "CONTROL MESH");
+ fp = vp;
+ count = fread((char *)fp, 1, nbytes, ifp);
+ if (count != nbytes) {
+ fprintf(stderr, "g2asc: control mesh read failure\n");
+ bu_exit(1, NULL);
+ }
+ /* Print the control mesh information */
+ count = record.d.d_ctl_size[0] * record.d.d_ctl_size[1] *
+ record.d.d_geom_type;
+ for (i = 0; i < count; i++) {
+ fprintf(ofp, "%.12e\n", *vp++);
+ }
+ /* Free the control mesh memory */
+ (void)bu_free((char *)fp, "CONTROL MESH");
+}
+
+/*
+ * Take a string and a length, and null terminate,
+ * converting unprintable characters to something printable.
+ */
+static char *
+strchop(char *str, size_t len)
+{
+ static char buf[10000] = {0};
+ char *ip = str;
+ char *op = buf;
+ int warn = 0;
+ char *ep;
+
+ CLAMP(len, 1, sizeof(buf)-2);
+
+ ep = &buf[len-1]; /* Leave room for null */
+ while (op < ep) {
+ if (*ip == '\0') break;
+ if ((int)isprint((int)*ip) || isspace((int)*ip)) {
+ *op++ = *ip++;
+ } else {
+ *op++ = '@';
+ ip++;
+ warn = 1;
+ }
+ }
+ *op = '\0';
+ if (warn) {
+ fprintf(stderr,
+ "g2asc: Illegal char in string, converted to '%s'\n",
+ buf);
+ }
+ if (op == buf) {
+ /* Null input name */
+ fprintf(stderr,
+ "g2asc: NULL string converted to -=STRING=-\n");
+ // TODO
+ //return "-=STRING=-";
+ return NULL;
+ }
+ return buf;
+}
+
+static void
+extrdump(void)
+{
+ struct rt_extrude_internal *extr;
+ int ngranules;
+ char *myname;
+ struct bu_external ext;
+ struct rt_db_internal intern;
+
+ myname = record.extr.ex_name;
+ ngranules = ntohl(*(uint32_t *)record.extr.ex_count) + 1;
+ get_ext(&ext, ngranules);
+
+ /* Hand off to librt's import() routine */
+ RT_DB_INTERNAL_INIT(&intern);
+ if ((OBJ[ID_EXTRUDE].ft_import4(&intern, &ext, id_mat, DBI_NULL,
&rt_uniresource)) != 0) {
+ fprintf(stderr, "g2asc: extrusion import failure\n");
+ bu_exit(-1, NULL);
+ }
+
+ extr = (struct rt_extrude_internal *)intern.idb_ptr;
+ RT_EXTRUDE_CK_MAGIC(extr);
+
+ fprintf(ofp, "%c ", DBID_EXTR); /* e */
+ fprintf(ofp, "%.16s ", encode_name(myname)); /* unique name */
+ fprintf(ofp, "%.16s ", encode_name(extr->sketch_name));
+ fprintf(ofp, "%d ", extr->keypoint);
+ fprintf(ofp, "%.12e %.12e %.12e ", V3ARGS(extr->V));
+ fprintf(ofp, "%.12e %.12e %.12e ", V3ARGS(extr->h));
+ fprintf(ofp, "%.12e %.12e %.12e ", V3ARGS(extr->u_vec));
+ fprintf(ofp, "%.12e %.12e %.12e\n", V3ARGS(extr->v_vec));
+}
+
+static void
+sketchdump(void)
+{
+ struct rt_sketch_internal *skt;
+ size_t ngranules;
+ char *myname;
+ struct bu_external ext;
+ struct rt_db_internal intern;
+ size_t i, j;
+ struct rt_curve *crv;
+
+ myname = record.skt.skt_name;
+ ngranules = ntohl(*(uint32_t *)record.skt.skt_count) + 1;
+ get_ext(&ext, ngranules);
+
+ /* Hand off to librt's import() routine */
+ RT_DB_INTERNAL_INIT(&intern);
+ if ((OBJ[ID_SKETCH].ft_import4(&intern, &ext, id_mat, DBI_NULL,
&rt_uniresource)) != 0) {
+ fprintf(stderr, "g2asc: sketch import failure\n");
+ bu_exit(-1, NULL);
+ }
+
+ skt = (struct rt_sketch_internal *)intern.idb_ptr;
+ RT_SKETCH_CK_MAGIC(skt);
+ crv = &skt->curve;
+ fprintf(ofp, "%c ", DBID_SKETCH); /* d */
+ fprintf(ofp, "%.16s ", encode_name(myname)); /* unique name */
+ fprintf(ofp, "%.12e %.12e %.12e ", V3ARGS(skt->V));
+ fprintf(ofp, "%.12e %.12e %.12e ", V3ARGS(skt->u_vec));
+ fprintf(ofp, "%.12e %.12e %.12e ", V3ARGS(skt->v_vec));
+ fprintf(ofp, "%lu %lu\n", (unsigned long)skt->vert_count, (unsigned
long)crv->count);
+ for (i = 0; i < skt->vert_count; i++)
+ fprintf(ofp, " %.12e %.12e", V2ARGS(skt->verts[i]));
+ fprintf(ofp, "\n");
+
+ for (j = 0; j < crv->count; j++) {
+ long *lng;
+ struct line_seg *lsg;
+ struct carc_seg *csg;
+ struct nurb_seg *nsg;
+ int k;
+
+ lng = (long *)crv->segment[j];
+ switch (*lng) {
+ case CURVE_LSEG_MAGIC:
+ lsg = (struct line_seg *)lng;
+ fprintf(ofp, " L %d %d %d\n", crv->reverse[j], lsg->start,
lsg->end);
+ break;
+ case CURVE_CARC_MAGIC:
+ csg = (struct carc_seg *)lng;
+ fprintf(ofp, " A %d %d %d %.12e %d %d\n", crv->reverse[j],
csg->start, csg->end,
+ csg->radius, csg->center_is_left,
csg->orientation);
+ break;
+ case CURVE_NURB_MAGIC:
+ nsg = (struct nurb_seg *)lng;
+ fprintf(ofp, " N %d %d %d %d %d\n ", crv->reverse[j],
nsg->order, nsg->pt_type,
+ nsg->k.k_size, nsg->c_size);
+ for (k = 0; k < nsg->k.k_size; k++)
+ fprintf(ofp, " %.12e", nsg->k.knots[k]);
+ fprintf(ofp, "\n ");
+ for (k = 0; k < nsg->c_size; k++)
+ fprintf(ofp, " %d", nsg->ctl_points[k]);
+ fprintf(ofp, "\n");
+ break;
+ }
+ }
+}
+
+int
+asc_write_v4(
+ struct gcv_context *UNUSED(c),
+ const struct gcv_opts *UNUSED(o),
+ const char *dest_path
+ )
+{
+ if (!dest_path) return 0;
+
+top:
+do {
+ /* A v4 record is already in the input buffer */
+ /* Check record type and skip deleted records */
+ switch (record.u_id) {
+ case ID_FREE:
+ continue;
+ case ID_SOLID:
+ soldump();
+ continue;
+ case ID_COMB:
+ if (combdump() > 0)
+ goto top;
+ continue;
+ case ID_MEMB:
+ fprintf(stderr, "g2asc: stray MEMB record, skipped\n");
+ continue;
+ case ID_ARS_A:
+ arsadump();
+ continue;
+ case ID_P_HEAD:
+ polyhead_asc();
+ continue;
+ case ID_P_DATA:
+ polydata_asc();
+ continue;
+ case ID_IDENT:
+ idendump();
+ continue;
+ case ID_MATERIAL:
+ materdump();
+ continue;
+ case DBID_PIPE:
+ pipe_dump();
+ continue;
+ case DBID_STRSOL:
+ strsol_dump();
+ continue;
+ case DBID_NMG:
+ nmg_dump();
+ continue;
+ case DBID_PARTICLE:
+ particle_dump();
+ continue;
+ case DBID_ARBN:
+ arbn_dump();
+ continue;
+ case DBID_CLINE:
+ cline_dump();
+ continue;
+ case DBID_BOT:
+ bot_dump();
+ continue;
+ case ID_BSOLID:
+ bspldump();
+ continue;
+ case ID_BSURF:
+ bsurfdump();
+ continue;
+ case DBID_SKETCH:
+ sketchdump();
+ continue;
+ case DBID_EXTR:
+ extrdump();
+ continue;
+ default:
+ fprintf(stderr,
+ "g2asc: unable to convert record type '%c' (0%o),
skipping\n",
+ record.u_id, record.u_id);
+ continue;
+ }
+ } while (fread((char *)&record, sizeof record, 1, ifp) == 1 &&
+ !feof(ifp));
+
+ return 1;
+}
+
// Local Variables:
// tab-width: 8
// mode: C++
Modified: brlcad/trunk/src/libgcv/plugins/asc/asc_v5.cpp
===================================================================
--- brlcad/trunk/src/libgcv/plugins/asc/asc_v5.cpp 2020-07-08 15:09:29 UTC
(rev 76284)
+++ brlcad/trunk/src/libgcv/plugins/asc/asc_v5.cpp 2020-07-08 16:18:01 UTC
(rev 76285)
@@ -32,6 +32,8 @@
#include <sstream>
#include <string>
+#include "bu/units.h"
+#include "raytrace.h"
#include "gcv/api.h"
#include "gcv/util.h"
@@ -44,6 +46,13 @@
{
std::string sline;
bu_log("Reading v5...\n");
+ /* Commands to handle:
+ *
+ * title
+ * units
+ * attr
+ * put
+ */
while (std::getline(fs, sline)) {
std::cout << sline << "\n";
}
@@ -50,6 +59,211 @@
return 1;
}
+
+static char *tclified_name=NULL;
+static size_t tclified_name_buffer_len=0;
+
+/* This routine escapes the '{' and '}' characters in any string and
returns a static buffer containing the
+ * resulting string. Used for names and db title on output.
+ *
+ * NOTE: RETURN OF STATIC BUFFER
+ */
+char *
+tclify_name(const char *name)
+{
+ const char *src=name;
+ char *dest;
+
+ size_t max_len=2 * strlen(name) + 1;
+
+ if (max_len < 2) {
+ return (char *)NULL;
+ }
+
+ if (max_len > tclified_name_buffer_len) {
+ tclified_name_buffer_len = max_len;
+ tclified_name = (char *)bu_realloc(tclified_name,
tclified_name_buffer_len, "tclified_name buffer");
+ }
+
+ dest = tclified_name;
+
+ while (*src) {
+ if (*src == '{' || *src == '}') {
+ *dest++ = '\\';
+ }
+ *dest++ = *src++;
+ }
+ *dest = '\0';
+
+ return tclified_name;
+}
+
+
+int
+asc_write_v5(
+ struct gcv_context *UNUSED(c),
+ const struct gcv_opts *UNUSED(o),
+ const char *dest_path
+ )
+{
+ FILE *v5ofp = NULL;
+ if (!dest_path) return 0;
+
+ struct db_i *dbip;
+ struct directory *dp;
+ const char *u;
+
+ if ((dbip = db_open(dest_path, DB_OPEN_READONLY)) == NULL) {
+ bu_log("Unable to open geometry database file '%s', aborting\n",
dest_path);
+ return 1;
+ }
+
+ RT_CK_DBI(dbip);
+ if (db_dirbuild(dbip)) {
+ bu_exit(1, "db_dirbuild failed\n");
+ }
+
+ /* write out the title and units special */
+ if (dbip->dbi_title[0]) {
+ fprintf(v5ofp, "title {%s}\n", tclify_name(dbip->dbi_title));
+ } else {
+ fprintf(v5ofp, "title {Untitled BRL-CAD Database}\n");
+ }
+ u = bu_units_string(dbip->dbi_local2base);
+ if (u) {
+ fprintf(v5ofp, "units %s\n", u);
+ }
+ FOR_ALL_DIRECTORY_START(dp, dbip) {
+ struct rt_db_internal intern;
+ struct bu_attribute_value_set *avs=NULL;
+
+ /* Process the _GLOBAL object */
+ if (dp->d_major_type == DB5_MAJORTYPE_ATTRIBUTE_ONLY &&
dp->d_minor_type == 0) {
+ const char *value;
+ struct bu_attribute_value_set g_avs;
+
+ /* get _GLOBAL attributes */
+ if (db5_get_attributes(dbip, &g_avs, dp)) {
+ bu_log("Failed to find any attributes on _GLOBAL\n");
+ continue;
+ }
+
+ /* save the associated attributes of
+ * _GLOBAL (except for title and units
+ * which were already written out) and
+ * regionid_colortable (which is written out below)
+ */
+ if (g_avs.count) {
+ int printedHeader = 0;
+ for (unsigned int i = 0; i < g_avs.count; i++) {
+ if (bu_strncmp(g_avs.avp[i].name, "title", 6) == 0) {
+ continue;
+ } else if (bu_strncmp(g_avs.avp[i].name, "units", 6) == 0) {
+ continue;
+ } else if (bu_strncmp(g_avs.avp[i].name,
"regionid_colortable", 19) == 0) {
+ continue;
+ } else if (strlen(g_avs.avp[i].name) <= 0) {
+ continue;
+ }
+ if (printedHeader == 0) {
+ fprintf(v5ofp, "attr set {_GLOBAL}");
+ printedHeader = 1;
+ }
+ fprintf(v5ofp, " {%s} {%s}", g_avs.avp[i].name,
g_avs.avp[i].value);
+ }
+ if (printedHeader == 1)
+ fprintf(v5ofp, "\n");
+ }
+
+ value = bu_avs_get(&g_avs, "regionid_colortable");
+ if (!value)
+ continue;
+ /* TODO - do this without Tcl */
+#if 0
+ size_t list_len;
+ list = Tcl_NewStringObj(value, -1);
+ {
+ int llen;
+ if (Tcl_ListObjLength(interp, list, &llen) != TCL_OK) {
+ bu_log("Failed to get length of region color table!!\n");
+ continue;
+ }
+ list_len = (size_t)llen;
+ }
+ for (i = 0; i < list_len; i++) {
+ if (Tcl_ListObjIndex(interp, list, i, &obj) != TCL_OK) {
+ bu_log("Cannot get entry %d from the color table!!\n",
+ i);
+ continue;
+ }
+ fprintf(v5ofp, "color %s\n",
+ Tcl_GetStringFromObj(obj, NULL));
+ }
+#endif
+ bu_avs_free(&g_avs);
+ continue;
+ }
+
+ if (rt_db_get_internal(&intern, dp, dbip, NULL, &rt_uniresource) < 0) {
+ bu_log("Unable to read '%s', skipping\n", dp->d_namep);
+ continue;
+ }
+ if (!intern.idb_meth->ft_get) {
+ bu_log("Unable to get '%s' (unimplemented), skipping\n",
dp->d_namep);
+ continue;
+ }
+
+ if (dp->d_flags & RT_DIR_COMB) {
+ struct bu_vls logstr = BU_VLS_INIT_ZERO;
+
+ if (intern.idb_meth->ft_get(&logstr, &intern, "tree") != 0) {
+ rt_db_free_internal(&intern);
+ bu_log("Unable to export '%s', skipping: %s\n", dp->d_namep,
bu_vls_cstr(&logstr));
+ bu_vls_free(&logstr);
+ continue;
+ }
+ if (dp->d_flags & RT_DIR_REGION) {
+ fprintf(v5ofp, "put {%s} comb region yes tree {%s}\n",
+ tclify_name(dp->d_namep),
+ bu_vls_cstr(&logstr));
+ } else {
+ fprintf(v5ofp, "put {%s} comb region no tree {%s}\n",
+ tclify_name(dp->d_namep),
+ bu_vls_cstr(&logstr));
+ }
+ bu_vls_free(&logstr);
+ } else {
+ struct bu_vls logstr = BU_VLS_INIT_ZERO;
+
+ if ((dp->d_minor_type != ID_CONSTRAINT) &&
(intern.idb_meth->ft_get(&logstr, &intern, NULL) != 0)) {
+ rt_db_free_internal(&intern);
+ bu_log("Unable to export '%s', skipping: %s\n", dp->d_namep,
bu_vls_cstr(&logstr));
+ bu_vls_free(&logstr);
+ continue;
+ }
+ fprintf(v5ofp, "put {%s} %s\n",
+ tclify_name(dp->d_namep),
+ bu_vls_cstr(&logstr));
+ bu_vls_free(&logstr);
+ }
+ avs = &intern.idb_avs;
+ if (avs->magic == BU_AVS_MAGIC && avs->count > 0) {
+ fprintf(v5ofp, "attr set {%s}", tclify_name(dp->d_namep));
+ for (unsigned int i = 0; i < avs->count; i++) {
+ if (strlen(avs->avp[i].name) <= 0) {
+ continue;
+ }
+ fprintf(v5ofp, " {%s}", avs->avp[i].name);
+ fprintf(v5ofp, " {%s}", avs->avp[i].value);
+ }
+ fprintf(v5ofp, "\n");
+ }
+ rt_db_free_internal(&intern);
+ } FOR_ALL_DIRECTORY_END;
+
+ return 1;
+}
+
// Local Variables:
// tab-width: 8
// mode: 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