BRL-CAD
wdb_importFg4Section.c
Go to the documentation of this file.
1 /* I M P O R T F G 4 S E C T I O N . C
2  * BRL-CAD
3  *
4  * Copyright (c) 1994-2014 United States Government as represented by
5  * the U.S. Army Research Laboratory.
6  *
7  * This library is free software; you can redistribute it and/or
8  * modify it under the terms of the GNU Lesser General Public License
9  * version 2.1 as published by the Free Software Foundation.
10  *
11  * This library is distributed in the hope that it will be useful, but
12  * WITHOUT ANY WARRANTY; without even the implied warranty of
13  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
14  * Lesser General Public License for more details.
15  *
16  * You should have received a copy of the GNU Lesser General Public
17  * License along with this file; see the file named COPYING for more
18  * information.
19  */
20 /** @addtogroup librt */
21 /** @{ */
22 /** @file libged/importFg4Section.c
23  *
24  * Some of this code was taken from conv/fast4-g.c and libwdb/bot.c
25  * and modified to behave as a method of the BRL-CAD database object
26  * that imports a Fastgen4 section from a string. This section can
27  * only contain GRIDs, CTRIs and CQUADs.
28  *
29  */
30 
31 #include "common.h"
32 
33 #include <stdlib.h>
34 #include <math.h>
35 #include <string.h>
36 #include <ctype.h>
37 #include <errno.h>
38 
39 #include "bu/debug.h"
40 #include "db.h"
41 #include "vmath.h"
42 #include "nmg.h"
43 #include "rtgeom.h"
44 #include "raytrace.h"
45 #include "ged.h"
46 #include "wdb.h"
47 #include "plot3.h"
48 
49 
50 static int grid_size; /* Number of points that will fit in current grid_pts array */
51 static int max_grid_no=0; /* Maximum grid number used */
52 static int mode=0; /* Plate mode (1) or volume mode (2), of current component */
53 static int group_id=(-1); /* Group identification number from SECTION card */
54 static int comp_id=(-1); /* Component identification number from SECTION card */
55 static int region_id=0; /* Region id number (group id no X 1000 + component id no) */
56 static char field[9]; /* Space for storing one field from an input line */
57 static int bot=0; /* Flag: >0 -> There are BOT's in current component */
58 static int debug=0; /* Debug flag */
59 
60 static int *FACES=NULL; /* one triplet per face indexing three grid points */
61 static fastf_t *THICKNESS; /* thickness of each face */
62 static char *facemode; /* mode for each face */
63 static int face_size=0; /* actual length of above arrays */
64 static int face_count=0; /* number of faces in above arrays */
65 
66 #define PLATE_MODE 1
67 #define VOLUME_MODE 2
68 
69 #define POS_CENTER 1 /* face positions for facets */
70 #define POS_FRONT 2
71 
72 #define END_OPEN 1 /* End closure codes for cones */
73 #define END_CLOSED 2
74 
75 #define GRID_BLOCK 256 /* allocate space for grid points in blocks of 256 points */
76 
77 #define CLINE 'l'
78 #define CHEX1 'p'
79 #define CHEX2 'b'
80 #define CTRI 't'
81 #define CQUAD 'q'
82 #define CCONE1 'c'
83 #define CCONE2 'd'
84 #define CCONE3 'e'
85 #define CSPHERE 's'
86 #define NMG 'n'
87 #define BOT 't'
88 #define COMPSPLT 'h'
89 
90 static point_t *grid_pts;
91 
92 
93 /*************************** code from libwdb/bot.c ***************************/
94 
95 static int
96 rt_mk_bot_w_normals(
97  struct rt_wdb *fp,
98  const char *name,
99  unsigned char botmode,
100  unsigned char orientation,
101  unsigned char flags,
102  int num_vertices,
103  int num_faces,
104  fastf_t *vertices, /* array of floats for vertices [num_vertices*3] */
105  int *faces, /* array of ints for faces [num_faces*3] */
106  fastf_t *thickness, /* array of plate mode thicknesses (corresponds to array of faces)
107  * NULL for modes RT_BOT_SURFACE and RT_BOT_SOLID.
108  */
109  struct bu_bitv *face_mode, /* a flag for each face indicating thickness is appended to hit point,
110  * otherwise thickness is centered about hit point
111  */
112  int num_normals, /* number of unit normals in normals array */
113  fastf_t *normals, /* array of floats for normals [num_normals*3] */
114  int *face_normals) /* array of ints (indices into normals array), must have 3*num_faces entries */
115 {
116  struct rt_bot_internal *botip;
117  int i;
118 
119  if ((num_normals > 0) && (db_version(fp->dbip) < 5)) {
120  bu_log("You are using an old database format which does not support surface normals for BOT primitives\n");
121  bu_log("You are attempting to create a BOT primitive named \"%s\" with surface normals\n" , name);
122  bu_log("The surface normals will not be saved\n");
123  bu_log("Please upgrade to the current database format by using \"dbupgrade\"\n");
124  }
125 
126  BU_ALLOC(botip, struct rt_bot_internal);
127  botip->magic = RT_BOT_INTERNAL_MAGIC;
128  botip->mode = botmode;
129  botip->orientation = orientation;
130  botip->bot_flags = flags;
131  botip->num_vertices = num_vertices;
132  botip->num_faces = num_faces;
133  botip->vertices = (fastf_t *)bu_calloc(num_vertices * 3, sizeof(fastf_t), "botip->vertices");
134  for (i = 0; i < num_vertices*3; i++)
135  botip->vertices[i] = vertices[i];
136  botip->faces = (int *)bu_calloc(num_faces * 3, sizeof(int), "botip->faces");
137  for (i = 0; i < num_faces * 3; i++)
138  botip->faces[i] = faces[i];
139  if (botmode == RT_BOT_PLATE) {
140  botip->thickness = (fastf_t *)bu_calloc(num_faces, sizeof(fastf_t), "botip->thickness");
141  for (i = 0; i < num_faces; i++)
142  botip->thickness[i] = thickness[i];
143  botip->face_mode = bu_bitv_dup(face_mode);
144  } else {
145  botip->thickness = (fastf_t *)NULL;
146  botip->face_mode = (struct bu_bitv *)NULL;
147  }
148 
149  if ((num_normals > 0) && (db_version(fp->dbip) > 4)) {
150  botip->num_normals = num_normals;
151  botip->num_face_normals = botip->num_faces;
152  botip->normals = (fastf_t *)bu_calloc(botip->num_normals * 3, sizeof(fastf_t), "BOT normals");
153  botip->face_normals = (int *)bu_calloc(botip->num_faces * 3, sizeof(int), "BOT face normals");
154  memcpy(botip->normals, normals, botip->num_normals * 3 * sizeof(fastf_t));
155  memcpy(botip->face_normals, face_normals, botip->num_faces * 3 * sizeof(int));
156  } else {
157  botip->bot_flags = 0;
158  botip->num_normals = 0;
159  botip->num_face_normals = 0;
160  botip->normals = (fastf_t *)NULL;
161  botip->face_normals = (int *)NULL;
162  }
163 
164  return wdb_export(fp, name, (void *)botip, ID_BOT, 1.0);
165 }
166 
167 
168 static int
169 rt_mk_bot(
170  struct rt_wdb *fp,
171  const char *name,
172  unsigned char botmode,
173  unsigned char orientation,
174  unsigned char flags,
175  int num_vertices,
176  int num_faces,
177  fastf_t *vertices, /* array of floats for vertices [num_vertices*3] */
178  int *faces, /* array of ints for faces [num_faces*3] */
179  fastf_t *thickness, /* array of plate mode thicknesses (corresponds to array of faces)
180  * NULL for modes RT_BOT_SURFACE and RT_BOT_SOLID.
181  */
182  struct bu_bitv *face_mode) /* a flag for each face indicating thickness is appended to hit point,
183  * otherwise thickness is centered about hit point
184  */
185 {
186  return (rt_mk_bot_w_normals(fp, name, botmode, orientation, flags, num_vertices, num_faces, vertices,
187  faces, thickness, face_mode, 0, NULL, NULL));
188 }
189 
190 
191 /*************************** code from conv/fast4-g.c ***************************/
192 
193 void
194 do_grid(char *line)
195 {
196  int grid_no;
197  fastf_t x, y, z;
198 
200  bu_log("ERROR: bu_mem_barriercheck failed at start of do_grid\n");
201 
202  bu_strlcpy(field, &line[8], sizeof(field));
203  grid_no = atoi(field);
204 
205  if (grid_no < 1) {
206  bu_log("ERROR: grid id number = %d\n", grid_no);
207  bu_bomb("BAD GRID ID NUMBER\n");
208  }
209 
210  bu_strlcpy(field, &line[24], sizeof(field));
211  x = atof(field);
212 
213  bu_strlcpy(field, &line[32], sizeof(field));
214  y = atof(field);
215 
216  bu_strlcpy(field, &line[40], sizeof(field));
217  z = atof(field);
218 
219  while (grid_no > grid_size - 1) {
220  grid_size += GRID_BLOCK;
221  grid_pts = (point_t *)bu_realloc((char *)grid_pts, grid_size * sizeof(point_t), "fast4-g: grid_pts");
222  }
223 
224  VSET(grid_pts[grid_no], x*25.4, y*25.4, z*25.4);
225 
226  if (grid_no > max_grid_no)
227  max_grid_no = grid_no;
229  bu_log("ERROR: bu_mem_barriercheck failed at end of do_grid\n");
230 }
231 
232 
233 void
234 Add_bot_face(int pt1, int pt2, int pt3, fastf_t thick, int pos)
235 {
236 
237  if (pt1 == pt2 || pt2 == pt3 || pt1 == pt3) {
238  bu_log("Add_bot_face: ignoring degenerate triangle in group %d component %d\n", group_id, comp_id);
239  return;
240  }
241 
242  if (pos == 0) /* use default */
243  pos = POS_FRONT;
244 
245  if (mode == PLATE_MODE) {
246  if (pos != POS_CENTER && pos != POS_FRONT) {
247  bu_log("Add_bot_face: illegal position parameter (%d), must be one or two (ignoring face for group %d component %d)\n", pos, group_id, comp_id);
248  return;
249  }
250  }
251 
252  if (face_count >= face_size) {
253  face_size += GRID_BLOCK;
255  bu_log("memory corrupted before realloc of faces, THICKNESS, and facemode\n");
256  FACES = (int *)bu_realloc((void *)FACES, face_size*3*sizeof(int), "faces");
257  THICKNESS = (fastf_t *)bu_realloc((void *)THICKNESS, face_size*sizeof(fastf_t), "thickness");
258  facemode = (char *)bu_realloc((void *)facemode, face_size*sizeof(char), "facemode");
260  bu_log("memory corrupted after realloc of faces, thickness, and facemode\n");
261  }
262 
263  FACES[face_count*3] = pt1;
264  FACES[face_count*3+1] = pt2;
265  FACES[face_count*3+2] = pt3;
266 
267  if (mode == PLATE_MODE) {
268  THICKNESS[face_count] = thick;
269  facemode[face_count] = pos;
270  } else {
271  THICKNESS[face_count] = 0;
272  facemode[face_count] = 0;
273  }
274 
275  face_count++;
276 
278  bu_log("memory corrupted at end of Add_bot_face()\n");
279 }
280 
281 
282 void
283 do_tri(char *line)
284 {
285  int element_id;
286  int pt1, pt2, pt3;
287  fastf_t thick;
288  int pos;
289 
290  if (debug)
291  bu_log("do_tri: %s\n", line);
292 
293  bu_strlcpy(field, &line[8], sizeof(field));
294  element_id = atoi(field);
295 
296  if (!bot)
297  bot = element_id;
298 
299  if (FACES == NULL) {
301  bu_log("memory corrupted before malloc of faces\n");
302  FACES = (int *)bu_malloc(GRID_BLOCK*3*sizeof(int), "faces");
303  THICKNESS = (fastf_t *)bu_malloc(GRID_BLOCK*sizeof(fastf_t), "thickness");
304  facemode = (char *)bu_malloc(GRID_BLOCK*sizeof(char), "facemode");
305  face_size = GRID_BLOCK;
306  face_count = 0;
308  bu_log("memory corrupted after malloc of faces, thickness, and facemode\n");
309  }
310 
311  bu_strlcpy(field, &line[24], sizeof(field));
312  pt1 = atoi(field);
313 
314  bu_strlcpy(field, &line[32], sizeof(field));
315  pt2 = atoi(field);
316 
317  bu_strlcpy(field, &line[40], sizeof(field));
318  pt3 = atoi(field);
319 
320  thick = 0.0;
321  pos = 0;
322 
323  if (mode == PLATE_MODE) {
324  bu_strlcpy(field, &line[56], sizeof(field));
325  thick = atof(field) * 25.4;
326 
327  bu_strlcpy(field, &line[64], sizeof(field));
328  pos = atoi(field);
329  if (pos == 0)
330  pos = POS_FRONT;
331 
332  if (debug)
333  bu_log("\tplate mode: thickness = %f\n", thick);
334 
335  }
336 
338  bu_log("memory corrupted before call to Add_bot_face()\n");
339 
340  Add_bot_face(pt1, pt2, pt3, thick, pos);
341 
343  bu_log("memory corrupted after call to Add_bot_face()\n");
344 }
345 
346 
347 void
348 do_quad(const char *line)
349 {
350  int element_id;
351  int pt1, pt2, pt3, pt4;
352  fastf_t thick = 0.0;
353  int pos = 0;
354 
355  bu_strlcpy(field, &line[8], sizeof(field));
356  element_id = atoi(field);
357 
358  if (debug)
359  bu_log("do_quad: %s\n", line);
360 
361  if (!bot)
362  bot = element_id;
363 
364  if (FACES == NULL) {
365  FACES = (int *)bu_malloc(GRID_BLOCK*3*sizeof(int), "faces");
366  THICKNESS = (fastf_t *)bu_malloc(GRID_BLOCK*sizeof(fastf_t), "thickness");
367  facemode = (char *)bu_malloc(GRID_BLOCK*sizeof(char), "facemode");
368  face_size = GRID_BLOCK;
369  face_count = 0;
370  }
371 
372  bu_strlcpy(field, &line[24], sizeof(field));
373  pt1 = atoi(field);
374 
375  bu_strlcpy(field, &line[32], sizeof(field));
376  pt2 = atoi(field);
377 
378  bu_strlcpy(field, &line[40], sizeof(field));
379  pt3 = atoi(field);
380 
381  bu_strlcpy(field, &line[48], sizeof(field));
382  pt4 = atoi(field);
383 
384  if (mode == PLATE_MODE) {
385  bu_strlcpy(field, &line[56], sizeof(field));
386  thick = atof(field) * 25.4;
387 
388  bu_strlcpy(field, &line[64], sizeof(field));
389  pos = atoi(field);
390 
391  if (pos == 0) /* use default */
392  pos = POS_FRONT;
393 
394  if (pos != POS_CENTER && pos != POS_FRONT) {
395  bu_log("do_quad: illegal position parameter (%d), must be one or two\n", pos);
396  bu_log("\telement %d, component %d, group %d\n", element_id, comp_id, group_id);
397  return;
398  }
399  }
400 
401  Add_bot_face(pt1, pt2, pt3, thick, pos);
402  Add_bot_face(pt1, pt3, pt4, thick, pos);
403 }
404 
405 
406 void
407 make_bot_object(const char *name,
408  struct rt_wdb *wdbp)
409 {
410  int i;
411  int max_pt=0, min_pt=999999;
412  int num_vertices;
413  struct bu_bitv *bv=NULL;
414  int bot_mode;
415  int count;
416  struct rt_bot_internal bot_ip;
417 
418  bot_ip.magic = RT_BOT_INTERNAL_MAGIC;
419  for (i = 0; i < face_count; i++) {
420  V_MIN(min_pt, FACES[i*3]);
421  V_MAX(max_pt, FACES[i*3]);
422  V_MIN(min_pt, FACES[i*3+1]);
423  V_MAX(max_pt, FACES[i*3+1]);
424  V_MIN(min_pt, FACES[i*3+2]);
425  V_MAX(max_pt, FACES[i*3+2]);
426  }
427 
428  num_vertices = max_pt - min_pt + 1;
429  bot_ip.num_vertices = num_vertices;
430  bot_ip.vertices = (fastf_t *)bu_calloc(num_vertices*3, sizeof(fastf_t), "BOT vertices");
431  for (i = 0; i < num_vertices; i++)
432  VMOVE(&bot_ip.vertices[i*3], grid_pts[min_pt+i]);
433 
434  for (i = 0; i < face_count*3; i++)
435  FACES[i] -= min_pt;
436  bot_ip.num_faces = face_count;
437  bot_ip.faces = (int *)bu_calloc(face_count*3, sizeof(int), "BOT faces");
438  for (i = 0; i < face_count*3; i++)
439  bot_ip.faces[i] = FACES[i];
440 
441  bot_ip.face_mode = (struct bu_bitv *)NULL;
442  bot_ip.thickness = (fastf_t *)NULL;
443  if (mode == PLATE_MODE) {
444  bot_mode = RT_BOT_PLATE;
445  bv = bu_bitv_new(face_count);
446  for (i = 0; i < face_count; i++) {
447  if (facemode[i] == POS_FRONT)
448  BU_BITSET(bv, i);
449  }
450  bot_ip.face_mode = bv;
451  bot_ip.thickness = (fastf_t *)bu_calloc(face_count, sizeof(fastf_t), "BOT thickness");
452  for (i = 0; i < face_count; i++)
453  bot_ip.thickness[i] = THICKNESS[i];
454  } else
455  bot_mode = RT_BOT_SOLID;
456 
457  bot_ip.mode = bot_mode;
458  bot_ip.orientation = RT_BOT_UNORIENTED;
459  bot_ip.bot_flags = 0;
460 
461  count = rt_bot_vertex_fuse(&bot_ip, &wdbp->wdb_tol);
462  count = rt_bot_face_fuse(&bot_ip);
463  if (count)
464  bu_log("WARNING: %d duplicate faces eliminated from group %d component %d\n", count, group_id, comp_id);
465 
466  rt_mk_bot(wdbp, name, bot_mode, RT_BOT_UNORIENTED, 0,
467  bot_ip.num_vertices, bot_ip.num_faces, bot_ip.vertices,
468  bot_ip.faces, bot_ip.thickness, bot_ip.face_mode);
469 
470  if (mode == PLATE_MODE) {
471  bu_free((char *)bot_ip.thickness, "BOT thickness");
472  bu_free((char *)bot_ip.face_mode, "BOT face_mode");
473  }
474  bu_free((char *)bot_ip.vertices, "BOT vertices");
475  bu_free((char *)bot_ip.faces, "BOT faces");
476 }
477 
478 
479 /*************************** Start of new code. ***************************/
480 
481 #define FIND_NEWLINE(_cp, _eosFlag) \
482  while (*(_cp) != '\0' && \
483  *(_cp) != '\n') \
484  ++(_cp); \
485  \
486  if (*(_cp) == '\0') \
487  _eosFlag = 1; \
488  else \
489  *(_cp) = '\0';
490 
491 int
493  int argc,
494  const char *argv[])
495 {
496  struct rt_wdb *wdbp = (struct rt_wdb *)data;
497  char *cp;
498  char *line;
499  char *lines;
500  int eosFlag = 0;
501 
502  if (argc != 3) {
503  bu_log("ERROR: expecting three arguments\n");
504  return TCL_ERROR;
505  }
506 
507  grid_size = GRID_BLOCK;
508  grid_pts = (point_t *)bu_malloc(grid_size * sizeof(point_t) ,
509  "importFg4Section: grid_pts");
510 
511  lines = strdup(argv[2]);
512  cp = line = lines;
513 
514  FIND_NEWLINE(cp, eosFlag);
515 
516  bu_strlcpy(field, line+8, sizeof(field));
517  group_id = atoi(field);
518 
519  bu_strlcpy(field, line+16, sizeof(field));
520  comp_id = atoi(field);
521 
522  region_id = group_id * 1000 + comp_id;
523 
524  if (comp_id > 999) {
525  bu_log("Illegal component id number %d, changed to 999\n", comp_id);
526  comp_id = 999;
527  }
528 
529  bu_strlcpy(field, line+24, sizeof(field));
530  mode = atoi(field);
531  if (mode != 1 && mode != 2) {
532  bu_log("Illegal mode (%d) for group %d component %d, using volume mode\n",
533  mode, group_id, comp_id);
534  mode = 2;
535  }
536 
537  while (!eosFlag) {
538  ++cp;
539  line = cp;
540  FIND_NEWLINE(cp, eosFlag);
541 
542  if (!bu_strncmp(line, "GRID", 4))
543  do_grid(line);
544  else if (!bu_strncmp(line, "CTRI", 4))
545  do_tri(line);
546  else if (!bu_strncmp(line, "CQUAD", 4))
547  do_quad(line);
548  }
549 
550  make_bot_object(argv[1], wdbp);
551  free((void *)lines);
552  bu_free((void *)grid_pts, "importFg4Section: grid_pts");
553 
554  /* free memory associated with globals */
555  bu_free((void *)FACES, "importFg4Section: faces");
556  bu_free((void *)THICKNESS, "importFg4Section: thickness");
557  bu_free((void *)facemode, "importFg4Section: facemode");
558 
559  FACES = NULL;
560  THICKNESS = NULL;
561  facemode = NULL;
562 
563  return TCL_OK;
564 }
565 /** @} */
566 
567 /*
568  * Local Variables:
569  * mode: C
570  * tab-width: 8
571  * indent-tabs-mode: t
572  * c-file-style: "stroustrup"
573  * End:
574  * ex: shiftwidth=4 tabstop=8
575  */
void do_grid(char *line)
void bu_log(const char *,...) _BU_ATTR_PRINTF12
Definition: log.c:176
struct bu_bitv * bu_bitv_new(size_t nbits)
Definition: bitv.c:91
#define BU_DEBUG_MEM_CHECK
Definition: debug.h:54
#define RT_BOT_INTERNAL_MAGIC
Definition: magic.h:85
#define GRID_BLOCK
void make_bot_object(const char *name, struct rt_wdb *wdbp)
struct db_i * dbip
Definition: raytrace.h:1266
Definition: clone.c:90
#define VSET(a, b, c, d)
Definition: color.c:53
#define ID_BOT
Bag o' triangles.
Definition: raytrace.h:488
int db_version(struct db_i *dbip)
Definition: db5_scan.c:414
Header file for the BRL-CAD common definitions.
#define BU_BITSET(_bv, bit)
Definition: bitv.h:183
void * bu_malloc(size_t siz, const char *str)
Definition: malloc.c:314
#define POS_FRONT
if(share_geom)
Definition: nmg_mod.c:3829
int rt_bot_vertex_fuse(struct rt_bot_internal *bot, const struct bn_tol *tol)
Definition: bot.c:3060
int bu_strncmp(const char *string1, const char *string2, size_t n)
Definition: str.c:191
COMPLEX data[64]
Definition: fftest.c:34
int wdb_export(struct rt_wdb *wdbp, const char *name, void *gp, int id, double local2mm)
Definition: wdb.c:265
#define RT_G_DEBUG
Definition: raytrace.h:1718
#define BU_ALLOC(_ptr, _type)
Definition: malloc.h:223
void * bu_calloc(size_t nelem, size_t elsize, const char *str)
Definition: malloc.c:321
#define bu_strlcpy(dst, src, size)
Definition: str.h:60
#define DEBUG_MEM_FULL
18 –>> BU_DEBUG_MEM_CHECK
Definition: raytrace.h:103
#define FIND_NEWLINE(_cp, _eosFlag)
void do_quad(const char *line)
void * bu_realloc(void *ptr, size_t siz, const char *str)
struct bu_bitv * bu_bitv_dup(const struct bu_bitv *bv)
int wdb_importFg4Section_cmd(void *data, int argc, const char *argv[])
int bu_mem_barriercheck(void)
Definition: malloc.c:660
int rt_bot_face_fuse(struct rt_bot_internal *bot)
Definition: bot.c:3283
int bu_debug
Definition: globals.c:87
#define PLATE_MODE
struct bn_tol wdb_tol
Definition: raytrace.h:1269
void Add_bot_face(int pt1, int pt2, int pt3, fastf_t thick, int pos)
char * strdup(const char *cp)
void bu_free(void *ptr, const char *str)
Definition: malloc.c:328
Definition: bitv.h:105
void do_tri(char *line)
void bu_bomb(const char *str) _BU_ATTR_NORETURN
Definition: bomb.c:91
double fastf_t
Definition: defines.h:300
#define POS_CENTER
eu1 orientation
Definition: nmg_mod.c:3916