BRL-CAD
fastgen4_read.c
Go to the documentation of this file.
1 /* F A S T 4 - G . 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 program 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 program 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  */
21 /** @file conv/fast4-g.c
22  *
23  * Program to convert the FASTGEN4 format to BRL-CAD.
24  *
25  */
26 
27 #include "common.h"
28 
29 /* system headers */
30 #include <stdlib.h>
31 #include <math.h>
32 #include <string.h>
33 #include <ctype.h>
34 #include <errno.h>
35 #include "bio.h"
36 
37 /* interface headers */
38 #include "bu/debug.h"
39 #include "bu/getopt.h"
40 #include "db.h"
41 #include "vmath.h"
42 #include "nmg.h"
43 #include "rtgeom.h"
44 #include "raytrace.h"
45 #include "wdb.h"
46 #include "plot3.h"
47 #include "../../plugin.h"
48 
49 
50 /* convenient macro for building regions */
51 #define MK_REGION(fp, headp, name, r_id, rgb) {\
52  if (mode == 1) {\
53  if (!quiet)\
54  bu_log("Making region: %s (PLATE)\n", name); \
55  mk_comb(fp, name, &((headp)->l), 'P', (char *)NULL, (char *)NULL, rgb, r_id, 0, 1, 100, 0, 0, 0); \
56  } else if (mode == 2) {\
57  if (!quiet) \
58  bu_log("Making region: %s (VOLUME)\n", name); \
59  mk_comb(fp, name, &((headp)->l), 'V', (char *)NULL, (char *)NULL, rgb, r_id, 0, 1, 100, 0, 0, 0); \
60  } else {\
61  bu_log("Illegal mode (%d), while trying to make region (%s)\n", mode, name);\
62  bu_log("\tRegion not made!\n");\
63  }\
64  }
65 
66 
67 #define PUSH(ptr) bu_ptbl_ins(&stack, (long *)ptr)
68 #define POP(structure, ptr) { \
69  if (BU_PTBL_END(&stack) == 0) \
70  ptr = (struct structure *)NULL; \
71  else { \
72  ptr = (struct structure *)BU_PTBL_GET(&stack, BU_PTBL_END(&stack)-1); \
73  bu_ptbl_rm(&stack, (long *)ptr); \
74  } \
75  }
76 #define PUSH2(ptr) bu_ptbl_ins(&stack2, (long *)ptr)
77 #define POP2(structure, ptr) { \
78  if (BU_PTBL_END(&stack2) == 0) \
79  ptr = (struct structure *)NULL; \
80  else { \
81  ptr = (struct structure *)BU_PTBL_GET(&stack2, BU_PTBL_END(&stack2)-1); \
82  bu_ptbl_rm(&stack2, (long *)ptr); \
83  } \
84  }
85 
86 
87 #define NAME_TREE_MAGIC 0x55555555
88 #define CK_TREE_MAGIC(ptr) {\
89  if (!ptr)\
90  bu_log("ERROR: Null name_tree pointer, file=%s, line=%d\n", __FILE__, __LINE__);\
91  else if (ptr->magic != NAME_TREE_MAGIC)\
92  bu_log("ERROR: bad name_tree pointer (%p), file=%s, line=%d\n", (void *)ptr, __FILE__, __LINE__);\
93  }
94 
95 
96 #define PLATE_MODE 1
97 #define VOLUME_MODE 2
98 
99 #define POS_CENTER 1 /* face positions for facets */
100 #define POS_FRONT 2
101 
102 #define END_OPEN 1 /* End closure codes for cones */
103 #define END_CLOSED 2
104 
105 #define GRID_BLOCK 256 /* allocate space for grid points in blocks of 256 points */
106 
107 #define CLINE 'l'
108 #define CHEX1 'p'
109 #define CHEX2 'b'
110 #define CTRI 't'
111 #define CQUAD 'q'
112 #define CCONE1 'c'
113 #define CCONE2 'd'
114 #define CCONE3 'e'
115 #define CSPHERE 's'
116 #define NMG 'n'
117 #define BOT 't'
118 #define COMPSPLT 'h'
119 
120 #define HOLE 1
121 #define WALL 2
122 #define INT_LIST_BLOCK 256 /* Number of int_list array slots to allocate */
123 #define MAX_LINE_SIZE 128 /* Length of char array for input line */
124 #define REGION_LIST_BLOCK 256 /* initial length of array of region ids to process */
125 
126 
127 struct fast4_color {
128  struct bu_list l;
129  short low;
130  short high;
131  unsigned char rgb[3];
132 };
133 
134 
135 struct cline {
136  int pt1, pt2;
138  int made;
141  struct cline *next;
142 } *cline_root;
143 
144 struct name_tree {
145  uint32_t magic;
147  int mode; /* PLATE_MODE or VOLUME_MODE */
148  int inner; /* 0 => this is a base/group name for a FASTGEN element */
149  int in_comp_group; /* > 0 -> region already in a component group */
150  char *name;
152 } *name_root;
153 
154 struct compsplt {
158  struct compsplt *next;
159 } *compsplt_root;
160 
161 struct hole_list {
162  int group;
164  struct hole_list *next;
165 };
166 
167 
168 struct holes {
169  int group;
171  int type;
172  struct hole_list *holes;
173  struct holes *next;
174 } *hole_root;
175 
176 
177 static int hex_faces[12][3]={
178  { 0, 1, 4 }, /* 1 */
179  { 1, 5, 4 }, /* 2 */
180  { 1, 2, 5 }, /* 3 */
181  { 2, 6, 5 }, /* 4 */
182  { 2, 3, 6 }, /* 5 */
183  { 3, 7, 6 }, /* 6 */
184  { 3, 0, 7 }, /* 7 */
185  { 0, 4, 7 }, /* 8 */
186  { 4, 6, 7 }, /* 9 */
187  { 4, 5, 6 }, /* 10 */
188  { 0, 1, 2 }, /* 11 */
189  { 0, 2, 3 } /* 12 */
190 };
191 
192 
193 static struct fast4_color HeadColor;
194 
195 static char line[MAX_LINE_SIZE+1]; /* Space for input line */
196 static FILE *fpin; /* Input FASTGEN4 file pointer */
197 static struct rt_wdb *fpout; /* Output BRL-CAD file pointer */
198 static FILE *fp_plot=NULL; /* file for plot output */
199 static FILE *fp_muves=NULL; /* file for MUVES data, output CHGCOMP and CBACKING data */
200 static int grid_size; /* Number of points that will fit in current grid_pts array */
201 static int max_grid_no=0; /* Maximum grid number used */
202 static int mode=0; /* Plate mode (1) or volume mode (2), of current component */
203 static int group_id=(-1); /* Group identification number from SECTION card */
204 static int comp_id=(-1); /* Component identification number from SECTION card */
205 static int region_id=0; /* Region id number (group id no X 1000 + component id no) */
206 static int region_id_max=0;
207 static char field[9]; /* Space for storing one field from an input line */
208 static char vehicle[17]; /* Title for BRL-CAD model from VEHICLE card */
209 static int name_count; /* Count of number of times this name_name has been used */
210 static int pass; /* Pass number (0 -> only make names, 1-> do geometry) */
211 static int bot=0; /* Flag: >0 -> There are BOT's in current component */
212 static int debug=0; /* Debug flag */
213 static int quiet=0; /* flag to not blather */
214 static int comp_count=0; /* Count of components in FASTGEN4 file */
215 static int f4_do_skips=0; /* flag indicating that not all components will be processed */
216 static int *region_list; /* array of region_ids to be processed */
217 static int region_list_len=0; /* actual length of the malloc'd region_list array */
218 static int f4_do_plot=0; /* flag indicating plot file should be created */
219 static struct wmember *group_head = (struct wmember *)NULL; /* Lists of regions for groups */
220 static ssize_t group_head_cnt=0;
221 static struct wmember hole_head; /* List of regions used as holes (not solid parts of model) */
222 static struct bu_ptbl stack; /* Stack for traversing name_tree */
223 static struct bu_ptbl stack2; /* Stack for traversing name_tree */
224 static fastf_t min_radius; /* minimum radius for TGC solids */
225 
226 static int *faces=NULL; /* one triplet per face indexing three grid points */
227 static fastf_t *thickness; /* thickness of each face */
228 static char *facemode; /* mode for each face */
229 static int face_size=0; /* actual length of above arrays */
230 static int face_count=0; /* number of faces in above arrays */
231 
232 /*static int *int_list;*/ /* Array of integers */
233 /*static int int_list_count=0;*/ /* Number of ints in above array */
234 /*static int int_list_length=0;*/ /* Length of int_list array */
235 
236 static point_t *grid_points = NULL;
237 
238 
239 static int
240 get_line(void)
241 {
242  int len, done;
243  struct bu_vls buffer = BU_VLS_INIT_ZERO;
244 
245  done = 0;
246  while (!done) {
247  len = bu_vls_gets(&buffer, fpin);
248  if (len < 0) goto out; /* eof or error */
249  if (len == 0) continue;
250  bu_vls_trimspace(&buffer);
251  len = bu_vls_strlen(&buffer);
252  if (len == 0) continue;
253  done = 1;
254  }
255 
256  if (len > MAX_LINE_SIZE)
257  bu_log("WARNING: long line truncated\n");
258 
259  memset((void *)line, 0, MAX_LINE_SIZE);
260  snprintf(line, MAX_LINE_SIZE, "%s", bu_vls_addr(&buffer));
261 
262 out:
263  bu_vls_free(&buffer);
264 
265  return len >= 0;
266 }
267 
268 
269 static unsigned char *
270 get_fast4_color(int r_id) {
271  struct fast4_color *fcp;
272 
273  for (BU_LIST_FOR(fcp, fast4_color, &HeadColor.l)) {
274  if (fcp->low <= r_id && r_id <= fcp->high)
275  return fcp->rgb;
276  }
277 
278  return (unsigned char *)NULL;
279 }
280 
281 
282 static int
283 is_a_hole(int id)
284 {
285  struct holes *hole_ptr;
286  struct hole_list *ptr;
287 
288  hole_ptr = hole_root;
289 
290  while (hole_ptr) {
291  if (hole_ptr->type == HOLE) {
292  ptr = hole_ptr->holes;
293  while (ptr) {
294  if ((ptr->group * 1000 + ptr->component) == id)
295  return 1;
296  ptr = ptr->next;
297  }
298  }
299  hole_ptr = hole_ptr->next;
300  }
301  return 0;
302 }
303 
304 
305 /*
306  static void
307  add_to_holes(char *name)
308  {
309  if (mk_addmember(name, &hole_head.l, NULL, WMOP_UNION) == (struct wmember *)NULL)
310  bu_log("add_to_holes: mk_addmember failed for region %s\n", name);
311  }
312 */
313 
314 
315 static void
316 plot_tri(int pt1, int pt2, int pt3)
317 {
318  pdv_3move(fp_plot, grid_points[pt1]);
319  pdv_3cont(fp_plot, grid_points[pt2]);
320  pdv_3cont(fp_plot, grid_points[pt3]);
321  pdv_3cont(fp_plot, grid_points[pt1]);
322 }
323 
324 
325 static void
326 Check_names(void)
327 {
328  struct name_tree *ptr;
329 
330  if (!name_root)
331  return;
332 
333  bu_ptbl_reset(&stack);
334 
336  /* ident order */
337  ptr = name_root;
338  while (1) {
339  while (ptr) {
340  PUSH(ptr);
341  ptr = ptr->rleft;
342  }
343  POP(name_tree, ptr);
344  if (!ptr)
345  break;
346 
347  /* visit node */
348  CK_TREE_MAGIC(ptr);
349  ptr = ptr->rright;
350  }
351 
352  /* alphabetical order */
353  ptr = name_root;
354  while (1) {
355  while (ptr) {
356  PUSH(ptr);
357  ptr = ptr->nleft;
358  }
359  POP(name_tree, ptr);
360  if (!ptr)
361  break;
362 
363  /* visit node */
364  CK_TREE_MAGIC(ptr);
365  ptr = ptr->nright;
366  }
367 }
368 
369 
370 static struct name_tree *
371 Search_names(struct name_tree *root, char *name, int *found)
372 {
373  struct name_tree *ptr;
374 
375  *found = 0;
376 
377  ptr = root;
378  if (!ptr)
379  return (struct name_tree *)NULL;
380 
381  while (1) {
382  int diff;
383 
384  diff = bu_strcmp(name, ptr->name);
385  if (diff == 0) {
386  *found = 1;
387  return ptr;
388  } else if (diff > 0) {
389  if (ptr->nright)
390  ptr = ptr->nright;
391  else
392  return ptr;
393  } else if (diff < 0) {
394  if (ptr->nleft)
395  ptr = ptr->nleft;
396  else
397  return ptr;
398  }
399  }
400 }
401 
402 
403 static struct name_tree *
404 Search_ident(struct name_tree *root, int reg_id, int *found)
405 {
406  struct name_tree *ptr;
407 
408  *found = 0;
409 
410  ptr = root;
411  if (!ptr)
412  return (struct name_tree *)NULL;
413 
414  while (1) {
415  int diff;
416 
417  diff = reg_id - ptr->region_id;
418 
419  if (diff == 0) {
420  *found = 1;
421  return ptr;
422  } else if (diff > 0) {
423  if (ptr->rright)
424  ptr = ptr->rright;
425  else
426  return ptr;
427  } else if (diff < 0) {
428  if (ptr->rleft)
429  ptr = ptr->rleft;
430  else
431  return ptr;
432  }
433  }
434 }
435 
436 
437 static void
438 List_names(void)
439 {
440  struct name_tree *ptr;
441 
442  bu_ptbl_reset(&stack);
443 
444  bu_log("\nNames in ident order:\n");
445  ptr = name_root;
446  while (1) {
447  while (ptr) {
448  PUSH(ptr);
449  ptr = ptr->rleft;
450  }
451  POP(name_tree, ptr);
452  if (!ptr)
453  break;
454 
455  if (ptr->in_comp_group)
456  bu_log("%s %d %d (in a comp group)\n", ptr->name, ptr->region_id, ptr->inner);
457  else
458  bu_log("%s %d %d (not in a comp group)\n", ptr->name, ptr->region_id, ptr->inner);
459  ptr = ptr->rright;
460  }
461 
462  bu_log("\tAlphabetical list of names:\n");
463  ptr = name_root;
464  while (1) {
465  while (ptr) {
466  PUSH(ptr);
467  ptr = ptr->nleft;
468  }
469  POP(name_tree, ptr);
470  if (!ptr)
471  break;
472 
473  bu_log("%s %d %d\n", ptr->name, ptr->region_id, ptr->inner);
474  ptr = ptr->nright;
475  }
476 }
477 
478 
479 static void
480 Insert_region_name(char *name, int reg_id)
481 {
482  struct name_tree *nptr_model, *rptr_model;
483  struct name_tree *new_ptr;
484  int foundn, foundr;
485 
486  if (debug)
487  bu_log("Insert_region_name(name=%s, reg_id=%d\n", name, reg_id);
488 
489  rptr_model = Search_ident(name_root, reg_id, &foundr);
490  nptr_model = Search_names(name_root, name, &foundn);
491 
492  if (foundn && foundr)
493  return;
494 
495  if (foundn != foundr) {
496  bu_log("Insert_region_name: name %s ident %d\n\tfound name is %d\n\tfound ident is %d\n",
497  name, reg_id, foundn, foundr);
498  List_names();
499  bu_exit(1, "\tCannot insert new node\n");
500  }
501 
502  /* Add to tree for entire model */
503  BU_ALLOC(new_ptr, struct name_tree);
504  new_ptr->rleft = (struct name_tree *)NULL;
505  new_ptr->rright = (struct name_tree *)NULL;
506  new_ptr->nleft = (struct name_tree *)NULL;
507  new_ptr->nright = (struct name_tree *)NULL;
508  new_ptr->region_id = reg_id;
509  new_ptr->mode = mode;
510  new_ptr->inner = -1;
511  new_ptr->in_comp_group = 0;
512  new_ptr->name = bu_strdup(name);
513  new_ptr->magic = NAME_TREE_MAGIC;
514 
515  V_MAX(region_id_max, reg_id);
516 
517  if (!name_root) {
518  name_root = new_ptr;
519  } else {
520  int diff;
521 
522  diff = bu_strcmp(name, nptr_model->name);
523 
524  if (diff > 0) {
525  if (nptr_model->nright) {
526  bu_log("Insert_region_name: nptr_model->nright not null\n");
527  bu_exit(1, "\tCannot insert new node\n");
528  }
529  nptr_model->nright = new_ptr;
530  } else {
531  if (nptr_model->nleft) {
532  bu_log("Insert_region_name: nptr_model->nleft not null\n");
533  bu_exit(1, "\tCannot insert new node\n");
534  }
535  nptr_model->nleft = new_ptr;
536  }
537 
538 
539  diff = reg_id - rptr_model->region_id;
540 
541  if (diff > 0) {
542  if (rptr_model->rright) {
543  bu_log("Insert_region_name: rptr_model->rright not null\n");
544  bu_exit(1, "\tCannot insert new node\n");
545  }
546  rptr_model->rright = new_ptr;
547  } else {
548  if (rptr_model->rleft) {
549  bu_log("Insert_region_name: rptr_model->rleft not null\n");
550  bu_exit(1, "\tCannot insert new node\n");
551  }
552  rptr_model->rleft = new_ptr;
553  }
554  }
555  Check_names();
557  bu_log("ERROR: bu_mem_barriercheck failed in Insert_region_name\n");
558 }
559 
560 
561 static char *
562 find_region_name(int g_id, int c_id)
563 {
564  struct name_tree *ptr;
565  int reg_id;
566  int found;
567 
568  reg_id = g_id * 1000 + c_id;
569 
570  if (debug)
571  bu_log("find_region_name(g_id=%d, c_id=%d), reg_id=%d\n", g_id, c_id, reg_id);
572 
573  ptr = Search_ident(name_root, reg_id, &found);
574 
575  if (found)
576  return ptr->name;
577  else
578  return (char *)NULL;
579 }
580 
581 
582 static char *
583 make_unique_name(char *name)
584 {
585  struct bu_vls vls = BU_VLS_INIT_ZERO;
586  int found;
587 
588  /* make a unique name from what we got off the $NAME card */
589 
590  (void)Search_names(name_root, name, &found);
591  if (!found)
592  return bu_strdup(name);
593 
594  while (found) {
595  bu_vls_trunc(&vls, 0);
596  bu_vls_printf(&vls, "%s_%d", name, name_count);
597  (void)Search_names(name_root, bu_vls_addr(&vls), &found);
598  }
600  bu_log("ERROR: bu_mem_barriercheck failed in make_unique_name\n");
601 
602  return bu_vls_strgrab(&vls);
603 }
604 
605 
606 static void
607 make_region_name(int g_id, int c_id)
608 {
609  int r_id;
610  const char *tmp_name;
611  char *name;
612 
613  r_id = g_id * 1000 + c_id;
614 
615  if (debug)
616  bu_log("make_region_name(g_id=%d, c_id=%d)\n", g_id, c_id);
617 
618  tmp_name = find_region_name(g_id, c_id);
619  if (tmp_name)
620  return;
621 
622  /* create a new name */
623  name = (char *)bu_malloc(MAX_LINE_SIZE, "make_region_name");
624  snprintf(name, MAX_LINE_SIZE, "comp_%04d.r", r_id);
625 
626  make_unique_name(name);
627 
628  Insert_region_name(name, r_id);
629 }
630 
631 
632 static char *
633 get_solid_name(char type, int element_id, int c_id, int g_id, int inner)
634 {
635  int reg_id;
636  struct bu_vls vls = BU_VLS_INIT_ZERO;
637 
638  reg_id = g_id * 1000 + c_id;
639 
640  bu_vls_printf(&vls, "%d.%d.%c%d", reg_id, element_id, type, inner);
641 
642  return bu_vls_strgrab(&vls);
643 }
644 
645 
646 static void
647 Insert_name(struct name_tree **root, char *name, int inner)
648 {
649  struct name_tree *ptr;
650  struct name_tree *new_ptr;
651  int found;
652  int diff;
653 
654  ptr = Search_names(*root, name, &found);
655 
656  if (found) {
657  bu_log("Insert_name: %s already in name tree\n", name);
658  return;
659  }
660 
661  BU_ALLOC(new_ptr, struct name_tree);
662 
663  new_ptr->name = bu_strdup(name);
664  new_ptr->nleft = (struct name_tree *)NULL;
665  new_ptr->nright = (struct name_tree *)NULL;
666  new_ptr->rleft = (struct name_tree *)NULL;
667  new_ptr->rright = (struct name_tree *)NULL;
668  new_ptr->region_id = (-region_id);
669  new_ptr->in_comp_group = 0;
670  new_ptr->inner = inner;
671  new_ptr->magic = NAME_TREE_MAGIC;
672 
673  if (!*root) {
674  *root = new_ptr;
675  return;
676  }
677 
678  diff = bu_strcmp(name, ptr->name);
679  if (diff > 0) {
680  if (ptr->nright) {
681  bu_log("Insert_name: ptr->nright not null\n");
682  bu_exit(1, "\tCannot insert new node\n");
683  }
684  ptr->nright = new_ptr;
685  } else {
686  if (ptr->nleft) {
687  bu_log("Insert_name: ptr->nleft not null\n");
688  bu_exit(1, "\tCannot insert new node\n");
689  }
690  ptr->nleft = new_ptr;
691  }
693  bu_log("ERROR: bu_mem_barriercheck failed in Insert_name\n");
694 }
695 
696 
697 static char *
698 make_solid_name(char type, int element_id, int c_id, int g_id, int inner)
699 {
700  char *name;
701 
702  name = get_solid_name(type, element_id, c_id, g_id, inner);
703 
704  Insert_name(&name_root, name, inner);
705 
706  return name;
707 }
708 
709 
710 static void
711 f4_do_compsplt(void)
712 {
713  int gr, co, gr1, co1;
714  fastf_t z;
715  struct compsplt *splt;
716 
717  bu_strlcpy(field, &line[8], sizeof(field));
718  gr = atoi(field);
719 
720  bu_strlcpy(field, &line[16], sizeof(field));
721  co = atoi(field);
722 
723  bu_strlcpy(field, &line[24], sizeof(field));
724  gr1 = atoi(field);
725 
726  bu_strlcpy(field, &line[32], sizeof(field));
727  co1 = atoi(field);
728 
729  bu_strlcpy(field, &line[40], sizeof(field));
730  z = atof(field) * 25.4;
731 
732  if (compsplt_root == NULL) {
734  splt = compsplt_root;
735  } else {
736  splt = compsplt_root;
737  while (splt->next)
738  splt = splt->next;
739  BU_ALLOC(splt->next, struct compsplt);
740  splt = splt->next;
741  }
742  splt->next = (struct compsplt *)NULL;
743  splt->ident_to_split = gr * 1000 + co;
744  splt->new_ident = gr1 * 1000 + co1;
745  splt->z = z;
746  make_region_name(gr1, co1);
747 }
748 
749 
750 static void
751 List_holes(void)
752 {
753  struct holes *hole_ptr;
754  struct hole_list *list_ptr;
755 
756  hole_ptr = hole_root;
757 
758  while (hole_ptr) {
759  bu_log("Holes for Group %d, Component %d:\n", hole_ptr->group, hole_ptr->component);
760  list_ptr = hole_ptr->holes;
761  while (list_ptr) {
762  bu_log("\tgroup %d component %d\n", list_ptr->group, list_ptr->component);
763  list_ptr = list_ptr->next;
764  }
765  hole_ptr = hole_ptr->next;
766  }
767 }
768 
769 
770 static void
771 Add_stragglers_to_groups(void)
772 {
773  struct name_tree *ptr;
774 
775  ptr = name_root;
776 
777  while (1) {
778  while (ptr) {
779  PUSH(ptr);
780  ptr = ptr->rleft;
781  }
782  POP(name_tree, ptr);
783  if (!ptr)
784  break;
785 
786  /* visit node */
787  CK_TREE_MAGIC(ptr);
788 
789  /* FIXME: should not be manually recreating the wmember list
790  * when extending it. just use a null-terminated list and
791  * realloc as needed...
792  */
793  if (!ptr->in_comp_group && ptr->region_id > 0 && !is_a_hole(ptr->region_id)) {
794  /* add this component to a series */
795 
796  if (!group_head || ptr->region_id > region_id_max) {
797  struct wmember *new_head;
798  ssize_t new_cnt, i;
799  struct bu_list *list_first;
800 
801  new_cnt = lrint(ceil(region_id_max/1000.0));
802  new_head = (struct wmember *)bu_calloc(new_cnt, sizeof(struct wmember), "group_head list");
803  bu_log("ptr->region_id=%d region_id_max=%d new_cnt=%ld\n", ptr->region_id, region_id_max, new_cnt);
804 
805  for (i = 0 ; i < new_cnt ; i++) {
806  BU_LIST_INIT(&new_head[i].l);
807  if (i < group_head_cnt) {
808  if (BU_LIST_NON_EMPTY(&group_head[i].l)) {
809  list_first = BU_LIST_FIRST(bu_list, &group_head[i].l);
810  BU_LIST_DEQUEUE(&group_head[i].l);
811  BU_LIST_INSERT(list_first, &new_head[i].l);
812  }
813  }
814  }
815  if (group_head) {
816  bu_free(group_head, "old group_head");
817  }
818  group_head = new_head;
819  group_head_cnt = new_cnt;
820  }
821 
822  (void)mk_addmember(ptr->name, &group_head[ptr->region_id/1000].l, NULL, WMOP_UNION);
823  ptr->in_comp_group = 1;
824  }
825 
826  ptr = ptr->rright;
827  }
828 }
829 
830 
831 static void
832 f4_do_groups(void)
833 {
834  int group_no;
835  struct wmember head_all;
836 
837  if (debug)
838  bu_log("f4_do_groups\n");
839 
840  BU_LIST_INIT(&head_all.l);
841 
842  Add_stragglers_to_groups();
843 
844  for (group_no=0; group_no < group_head_cnt; group_no++) {
845  char name[MAX_LINE_SIZE] = {0};
846 
847  if (BU_LIST_IS_EMPTY(&group_head[group_no].l))
848  continue;
849 
850  snprintf(name, MAX_LINE_SIZE, "%dxxx_series", group_no);
851  mk_lfcomb(fpout, name, &group_head[group_no], 0);
852 
853  if (mk_addmember(name, &head_all.l, NULL, WMOP_UNION) == (struct wmember *)NULL)
854  bu_log("f4_do_groups: mk_addmember failed to add %s to group all\n", name);
855  }
856 
857  if (BU_LIST_NON_EMPTY(&head_all.l))
858  mk_lfcomb(fpout, "all", &head_all, 0);
859 
860  if (BU_LIST_NON_EMPTY(&hole_head.l))
861  mk_lfcomb(fpout, "holes", &hole_head, 0);
862 }
863 
864 
865 static void
866 f4_do_name(void)
867 {
868  int i, j;
869  int g_id;
870  int c_id;
871  char comp_name[MAX_LINE_SIZE] = {0}; /* should only use 25 chars */
872  char tmp_name[MAX_LINE_SIZE] = {0}; /* should only use 25 chars */
873 
874  if (pass)
875  return;
876 
877  if (debug)
878  bu_log("f4_do_name: %s\n", line);
879 
880  bu_strlcpy(field, &line[8], sizeof(field));
881  g_id = atoi(field);
882 
883  if (g_id != group_id) {
884  bu_log("$NAME card for group %d in section for group %d ignored\n", g_id, group_id);
885  bu_log("%s\n", line);
886  return;
887  }
888 
889  bu_strlcpy(field, &line[16], sizeof(field));
890  c_id = atoi(field);
891 
892  if (c_id != comp_id) {
893  bu_log("$NAME card for component %d in section for component %d ignored\n", c_id, comp_id);
894  bu_log("%s\n", line);
895  return;
896  }
897 
898  /* skip leading blanks */
899  i = 56;
900  while ((size_t)i < sizeof(comp_name) && isspace((int)line[i]))
901  i++;
902 
903  if (i == sizeof(comp_name))
904  return;
905 
906  bu_strlcpy(comp_name, &line[i], sizeof(comp_name) - i);
907 
908  /* eliminate trailing blanks */
909  i = sizeof(comp_name) - i;
910  while (--i >= 0 && isspace((int)comp_name[i]))
911  comp_name[i] = '\0';
912 
913  /* copy comp_name to tmp_name while replacing white space with "_" */
914  i = (-1);
915  j = (-1);
916 
917  /* copy */
918  while (comp_name[++i] != '\0') {
919  if (isspace((int)comp_name[i]) || comp_name[i] == '/') {
920  if (j == (-1) || tmp_name[j] != '_')
921  tmp_name[++j] = '_';
922  } else {
923  tmp_name[++j] = comp_name[i];
924  }
925  }
926  tmp_name[++j] = '\0';
927 
928  /* reserve this name for group name */
929  make_unique_name(tmp_name);
930  Insert_region_name(tmp_name, region_id);
931 
932  name_count = 0;
934  bu_log("ERROR: bu_mem_barriercheck failed in f4_do_name\n");
935 }
936 
937 
938 static void
939 f4_do_grid(void)
940 {
941  int grid_no;
942  fastf_t x, y, z;
943 
944  if (!pass) /* not doing geometry yet */
945  return;
946 
948  bu_log("ERROR: bu_mem_barriercheck failed at start of f4_do_grid\n");
949 
950  bu_strlcpy(field, &line[8], sizeof(field));
951  grid_no = atoi(field);
952 
953  if (grid_no < 1) {
954  bu_exit(1, "ERROR: bad grid id number = %d\n", grid_no);
955  }
956 
957  bu_strlcpy(field, &line[24], sizeof(field));
958  x = atof(field);
959 
960  bu_strlcpy(field, &line[32], sizeof(field));
961  y = atof(field);
962 
963  bu_strlcpy(field, &line[40], sizeof(field));
964  z = atof(field);
965 
966  while (grid_no > grid_size - 1) {
967  grid_size += GRID_BLOCK;
968  grid_points = (point_t *)bu_realloc((char *)grid_points, grid_size * sizeof(point_t), "fast4-g: grid_points");
969  }
970 
971  VSET(grid_points[grid_no], x*25.4, y*25.4, z*25.4);
972 
973  V_MAX(max_grid_no, grid_no);
974 
976  bu_log("ERROR: bu_mem_barriercheck failed at end of f4_do_grid\n");
977 }
978 
979 
980 static void
981 f4_do_sphere(void)
982 {
983  int element_id;
984  int center_pt;
985  fastf_t thick;
986  fastf_t radius;
987  fastf_t inner_radius;
988  char *name = (char *)NULL;
989  struct wmember sphere_group;
990 
991  if (!pass) {
992  make_region_name(group_id, comp_id);
993  return;
994  }
995 
996  bu_strlcpy(field, &line[8], sizeof(field));
997  element_id = atoi(field);
998 
999  bu_strlcpy(field, &line[24], sizeof(field));
1000  center_pt = atoi(field);
1001 
1002  bu_strlcpy(field, &line[56], sizeof(field));
1003  thick = atof(field) * 25.4;
1004 
1005  bu_strlcpy(field, &line[64], sizeof(field));
1006  radius = atof(field) * 25.4;
1007 
1008  if (radius <= 0.0) {
1009  bu_log("f4_do_sphere: illegal radius (%f), skipping sphere\n", radius);
1010  bu_log("\telement %d, component %d, group %d\n", element_id, comp_id, group_id);
1011  return;
1012  }
1013 
1014  if (center_pt < 1 || center_pt > max_grid_no) {
1015  bu_log("f4_do_sphere: illegal grid number for center point %d, skipping sphere\n", center_pt);
1016  bu_log("\telement %d, component %d, group %d\n", element_id, comp_id, group_id);
1017  return;
1018  }
1019 
1020  BU_LIST_INIT(&sphere_group.l);
1021 
1022  if (mode == VOLUME_MODE) {
1023  name = make_solid_name(CSPHERE, element_id, comp_id, group_id, 0);
1024  mk_sph(fpout, name, grid_points[center_pt], radius);
1025  bu_free(name, "solid_name");
1026  } else if (mode == PLATE_MODE) {
1027  name = make_solid_name(CSPHERE, element_id, comp_id, group_id, 1);
1028  mk_sph(fpout, name, grid_points[center_pt], radius);
1029 
1030  BU_LIST_INIT(&sphere_group.l);
1031 
1032  if (mk_addmember(name, &sphere_group.l, NULL, WMOP_UNION) == (struct wmember *)NULL) {
1033  bu_exit(1, "f4_do_sphere: Error in adding %s to sphere group\n", name);
1034  }
1035  bu_free(name, "solid_name");
1036 
1037  inner_radius = radius - thick;
1038  if (thick > 0.0 && inner_radius <= 0.0) {
1039  bu_log("f4_do_sphere: illegal thickness (%f), skipping inner sphere\n", thick);
1040  bu_log("\telement %d, component %d, group %d\n", element_id, comp_id, group_id);
1041  return;
1042  }
1043 
1044  name = make_solid_name(CSPHERE, element_id, comp_id, group_id, 2);
1045  mk_sph(fpout, name, grid_points[center_pt], inner_radius);
1046 
1047  if (mk_addmember(name, &sphere_group.l, NULL, WMOP_SUBTRACT) == (struct wmember *)NULL) {
1048  bu_exit(1, "f4_do_sphere: Error in subtracting %s from sphere region\n", name);
1049  }
1050  bu_free(name, "solid_name");
1051 
1052  name = make_solid_name(CSPHERE, element_id, comp_id, group_id, 0);
1053  mk_comb(fpout, name, &sphere_group.l, 0, NULL, NULL, NULL, 0, 0, 0, 0, 0, 1, 1);
1054  bu_free(name, "solid_name");
1055  }
1056 }
1057 
1058 
1059 static void
1060 f4_do_vehicle(void)
1061 {
1062  if (pass)
1063  return;
1064 
1065  bu_strlcpy(vehicle, &line[8], sizeof(vehicle));
1066  mk_id_units(fpout, vehicle, "in");
1067 }
1068 
1069 
1070 static void
1071 f4_do_cline(void)
1072 {
1073  int element_id;
1074  int pt1, pt2;
1075  fastf_t thick;
1076  fastf_t radius;
1077  vect_t height;
1078  char *name;
1079 
1080  if (debug)
1081  bu_log("f4_do_cline: %s\n", line);
1082 
1083  if (!pass) {
1084  make_region_name(group_id, comp_id);
1085  return;
1086  }
1087 
1088  bu_strlcpy(field, &line[8], sizeof(field));
1089  element_id = atoi(field);
1090 
1091  bu_strlcpy(field, &line[24], sizeof(field));
1092  pt1 = atoi(field);
1093 
1094  if (pass && (pt1 < 1 || pt1 > max_grid_no)) {
1095  bu_log("Illegal grid point (%d) in CLINE, skipping\n", pt1);
1096  bu_log("\telement %d, component %d, group %d\n", element_id, comp_id, group_id);
1097  return;
1098  }
1099 
1100  bu_strlcpy(field, &line[32], sizeof(field));
1101  pt2 = atoi(field);
1102 
1103  if (pass && (pt2 < 1 || pt2 > max_grid_no)) {
1104  bu_log("Illegal grid point in CLINE (%d), skipping\n", pt2);
1105  bu_log("\telement %d, component %d, group %d\n", element_id, comp_id, group_id);
1106  return;
1107  }
1108 
1109  if (pt1 == pt2) {
1110  bu_log("Illegal grid points in CLINE (%d and %d), skipping\n", pt1, pt2);
1111  bu_log("\telement %d, component %d, group %d\n", element_id, comp_id, group_id);
1112  return;
1113  }
1114 
1115  bu_strlcpy(field, &line[56], sizeof(field));
1116  thick = atof(field) * 25.4;
1117 
1118  bu_strlcpy(field, &line[64], sizeof(field));
1119  radius = atof(field) * 25.4;
1120 
1121  VSUB2(height, grid_points[pt2], grid_points[pt1]);
1122 
1123  name = make_solid_name(CLINE, element_id, comp_id, group_id, 0);
1124  mk_cline(fpout, name, grid_points[pt1], height, radius, thick);
1125  bu_free(name, "solid_name");
1126 }
1127 
1128 
1129 static void
1130 f4_do_ccone1(void)
1131 {
1132  int element_id;
1133  int pt1, pt2;
1134  fastf_t thick;
1135  int c1, c2;
1136  int end1, end2;
1137  vect_t height;
1138  fastf_t r1, r2;
1139  char *outer_name;
1140  char *inner_name;
1141  char *name = (char *)NULL;
1142  struct wmember r_head;
1143 
1144  bu_strlcpy(field, &line[8], sizeof(field));
1145  element_id = atoi(field);
1146 
1147  if (!pass) {
1148  make_region_name(group_id, comp_id);
1149  if (!get_line()) {
1150  bu_log("Unexpected EOF while reading continuation card for CCONE1\n");
1151  bu_log("\tgroup_id = %d, comp_id = %d, element_id = %d\n",
1152  group_id, comp_id, element_id);
1153  bu_exit(1, "ERROR: unexpected end-of-file");
1154  }
1155  return;
1156  }
1157 
1158  bu_strlcpy(field, &line[24], sizeof(field));
1159  pt1 = atoi(field);
1160 
1161  bu_strlcpy(field, &line[32], sizeof(field));
1162  pt2 = atoi(field);
1163 
1164  bu_strlcpy(field, &line[56], sizeof(field));
1165  thick = atof(field) * 25.4;
1166 
1167  bu_strlcpy(field, &line[64], sizeof(field));
1168  r1 = atof(field) * 25.4;
1169 
1170  bu_strlcpy(field, &line[72], sizeof(field));
1171  c1 = atoi(field);
1172 
1173  if (!get_line()) {
1174  bu_log("Unexpected EOF while reading continuation card for CCONE1\n");
1175  bu_log("\tgroup_id = %d, comp_id = %d, element_id = %d, c1 = %d\n",
1176  group_id, comp_id, element_id, c1);
1177  bu_exit(1, "ERROR: unexpected end-of-file");
1178  }
1179 
1180  bu_strlcpy(field, line, sizeof(field));
1181  c2 = atoi(field);
1182 
1183  if (c1 != c2) {
1184  bu_log("WARNING: CCONE1 continuation flags disagree, %d vs %d\n", c1, c2);
1185  bu_log("\tgroup_id = %d, comp_id = %d, element_id = %d\n",
1186  group_id, comp_id, element_id);
1187  }
1188 
1189  bu_strlcpy(field, &line[8], sizeof(field));
1190  r2 = atof(field) * 25.4;
1191 
1192  bu_strlcpy(field, &line[16], sizeof(field));
1193  end1 = atoi(field);
1194 
1195  bu_strlcpy(field, &line[24], sizeof(field));
1196  end2 = atoi(field);
1197 
1198  if (r1 < 0.0 || r2 < 0.0) {
1199  bu_log("ERROR: CCONE1 has illegal radii, %f and %f\n", r1/25.4, r2/25.4);
1200  bu_log("\tgroup_id = %d, comp_id = %d, element_id = %d\n",
1201  group_id, comp_id, element_id);
1202  bu_log("\tCCONE1 solid ignored\n");
1203  return;
1204  }
1205 
1206  if (mode == PLATE_MODE) {
1207  if (thick <= 0.0) {
1208  bu_log("WARNING: Plate mode CCONE1 has illegal thickness (%f)\n", thick/25.4);
1209  bu_log("\tgroup_id = %d, comp_id = %d, element_id = %d\n",
1210  group_id, comp_id, element_id);
1211  bu_log("\tCCONE1 solid plate mode overridden, now being treated as volume mode\n");
1212  mode = VOLUME_MODE;
1213  }
1214  }
1215 
1216  if (mode == PLATE_MODE) {
1217  if (r1-thick < min_radius && r2-thick < min_radius) {
1218  bu_log("ERROR: Plate mode CCONE1 has too large thickness (%f)\n", thick/25.4);
1219  bu_log("\tgroup_id = %d, comp_id = %d, element_id = %d\n",
1220  group_id, comp_id, element_id);
1221  bu_log("\tCCONE1 solid ignored\n");
1222  return;
1223  }
1224  }
1225 
1226  if (pt1 < 1 || pt1 > max_grid_no || pt2 < 1 || pt2 > max_grid_no || pt1 == pt2) {
1227  bu_log("ERROR: CCONE1 has illegal grid points (%d and %d)\n", pt1, pt2);
1228  bu_log("\tgroup_id = %d, comp_id = %d, element_id = %d\n",
1229  group_id, comp_id, element_id);
1230  bu_log("\tCCONE1 solid ignored\n");
1231  return;
1232  }
1233 
1234  /* BRL_CAD doesn't allow zero radius, so use a very small radius */
1235  V_MAX(r1, min_radius);
1236  V_MAX(r2, min_radius);
1237 
1238  VSUB2(height, grid_points[pt2], grid_points[pt1]);
1239 
1240  if (mode == VOLUME_MODE) {
1241  outer_name = make_solid_name(CCONE1, element_id, comp_id, group_id, 0);
1242  mk_trc_h(fpout, outer_name, grid_points[pt1], height, r1, r2);
1243  bu_free(outer_name, "solid_name");
1244  } else if (mode == PLATE_MODE) {
1245  /* make inside TGC */
1246 
1247  point_t base;
1248  point_t top;
1249  vect_t inner_height;
1250  fastf_t inner_r1, inner_r2;
1251  fastf_t length;
1252  fastf_t sin_ang;
1253  fastf_t slant_len;
1254  fastf_t r1a, r2a;
1255  vect_t height_dir;
1256 
1257  /* make outside TGC */
1258  outer_name = make_solid_name(CCONE1, element_id, comp_id, group_id, 1);
1259  mk_trc_h(fpout, outer_name, grid_points[pt1], height, r1, r2);
1260 
1261  BU_LIST_INIT(&r_head.l);
1262  if (mk_addmember(outer_name, &r_head.l, NULL, WMOP_UNION) == (struct wmember *)NULL)
1263  bu_exit(1, "CCONE1: mk_addmember failed\n");
1264  bu_free(outer_name, "solid_name");
1265 
1266  length = MAGNITUDE(height);
1267  VSCALE(height_dir, height, 1.0/length);
1268  slant_len = sqrt(length*length + (r2 - r1)*(r2 - r1));
1269 
1270  sin_ang = length/slant_len;
1271 
1272  if (end1 == END_OPEN) {
1273  r1a = r1;
1274  inner_r1 = r1 - thick/sin_ang;
1275  VMOVE(base, grid_points[pt1]);
1276  } else {
1277  r1a = r1 + (r2 - r1)*thick/length;
1278  inner_r1 = r1a - thick/sin_ang;
1279  VJOIN1(base, grid_points[pt1], thick, height_dir);
1280  }
1281 
1282  if (inner_r1 < 0.0) {
1283  fastf_t dist_to_new_base;
1284 
1285  dist_to_new_base = inner_r1 * length/(r1 - r2);
1286  inner_r1 = min_radius;
1287  VJOIN1(base, base, dist_to_new_base, height_dir);
1288  } else {
1289  V_MAX(inner_r1, min_radius);
1290  }
1291 
1292  if (end2 == END_OPEN) {
1293  r2a = r2;
1294  inner_r2 = r2 - thick/sin_ang;
1295  VMOVE(top, grid_points[pt2]);
1296  } else {
1297  r2a = r2 + (r1 - r2)*thick/length;
1298  inner_r2 = r2a - thick/sin_ang;
1299  VJOIN1(top, grid_points[pt2], -thick, height_dir);
1300  }
1301 
1302  if (inner_r2 < 0.0) {
1303  fastf_t dist_to_new_top;
1304 
1305  dist_to_new_top = inner_r2 * length/(r2 - r1);
1306  inner_r2 = min_radius;
1307  VJOIN1(top, top, -dist_to_new_top, height_dir);
1308  } else {
1309  V_MAX(inner_r2, min_radius);
1310  }
1311 
1312  VSUB2(inner_height, top, base);
1313  if (VDOT(inner_height, height) <= 0.0) {
1314  bu_log("ERROR: CCONE1 height (%f) too small for thickness (%f)\n", length/25.4, thick/25.4);
1315  bu_log("\tgroup_id = %d, comp_id = %d, element_id = %d\n",
1316  group_id, comp_id, element_id);
1317  bu_log("\tCCONE1 inner solid ignored\n");
1318  } else {
1319  /* make inner tgc */
1320 
1321  inner_name = make_solid_name(CCONE1, element_id, comp_id, group_id, 2);
1322  mk_trc_h(fpout, inner_name, base, inner_height, inner_r1, inner_r2);
1323 
1324  if (mk_addmember(inner_name, &r_head.l, NULL, WMOP_SUBTRACT) == (struct wmember *)NULL)
1325  bu_exit(1, "CCONE1: mk_addmember failed\n");
1326  bu_free(inner_name, "solid_name");
1327  }
1328 
1329  name = make_solid_name(CCONE1, element_id, comp_id, group_id, 0);
1330  mk_comb(fpout, name, &r_head.l, 0, NULL, NULL, NULL, 0, 0, 0, 0, 0, 1, 1);
1331  bu_free(name, "solid_name");
1332  }
1333 
1334 }
1335 
1336 
1337 static void
1338 f4_do_ccone2(void)
1339 {
1340  int element_id;
1341  int pt1, pt2;
1342  int c1, c2;
1343  fastf_t ro1, ro2, ri1, ri2;
1344  vect_t height;
1345  char *name = (char *)NULL;
1346  struct wmember r_head;
1347 
1348  bu_strlcpy(field, &line[8], sizeof(field));
1349  element_id = atoi(field);
1350 
1351  if (!pass) {
1352  make_region_name(group_id, comp_id);
1353  if (!get_line()) {
1354  bu_log("Unexpected EOF while reading continuation card for CCONE2\n");
1355  bu_log("\tgroup_id = %d, comp_id = %d, element_id = %d\n",
1356  group_id, comp_id, element_id);
1357  bu_exit(1, "ERROR: unexpected end-of-file encountered\n");
1358  }
1359  return;
1360  }
1361 
1362  bu_strlcpy(field, &line[24], sizeof(field));
1363  pt1 = atoi(field);
1364 
1365  bu_strlcpy(field, &line[32], sizeof(field));
1366  pt2 = atoi(field);
1367 
1368  bu_strlcpy(field, &line[64], sizeof(field));
1369  ro1 = atof(field) * 25.4;
1370 
1371  bu_strlcpy(field, &line[72], sizeof(field));
1372  c1 = atoi(field);
1373 
1374  if (!get_line()) {
1375  bu_log("Unexpected EOF while reading continuation card for CCONE2\n");
1376  bu_log("\tgroup_id = %d, comp_id = %d, element_id = %d, c1 = %d\n",
1377  group_id, comp_id, element_id, c1);
1378  bu_exit(1, "ERROR: unexpected end-of-file encountered\n");
1379  }
1380 
1381  bu_strlcpy(field, line, sizeof(field));
1382  c2 = atoi(field);
1383 
1384  if (c1 != c2) {
1385  bu_log("WARNING: CCONE2 continuation flags disagree, %d vs %d\n", c1, c2);
1386  bu_log("\tgroup_id = %d, comp_id = %d, element_id = %d\n",
1387  group_id, comp_id, element_id);
1388  }
1389 
1390  bu_strlcpy(field, &line[8], sizeof(field));
1391  ro2 = atof(field) * 25.4;
1392 
1393  bu_strlcpy(field, &line[16], sizeof(field));
1394  ri1 = atof(field) * 25.4;
1395 
1396  bu_strlcpy(field, &line[24], sizeof(field));
1397  ri2 = atof(field) * 25.4;
1398 
1399  if (pt1 == pt2) {
1400  bu_log("ERROR: CCONE2 has same endpoints %d and %d\n", pt1, pt2);
1401  bu_log("\tgroup_id = %d, comp_id = %d, element_id = %d\n",
1402  group_id, comp_id, element_id);
1403  return;
1404  }
1405 
1406  if (ro1 < 0.0 || ro2 < 0.0 || ri1 < 0.0 || ri2 < 0.0) {
1407  bu_log("ERROR: CCONE2 has illegal radii %f %f %f %f\n", ro1, ro2, ri1, ri2);
1408  bu_log("\tgroup_id = %d, comp_id = %d, element_id = %d\n",
1409  group_id, comp_id, element_id);
1410  return;
1411  }
1412 
1413  V_MAX(ro1, min_radius);
1414  V_MAX(ro2, min_radius);
1415 
1416  BU_LIST_INIT(&r_head.l);
1417 
1418  VSUB2(height, grid_points[pt2], grid_points[pt1]);
1419 
1420  if (ri1 <= 0.0 && ri2 <= 0.0) {
1421  name = make_solid_name(CCONE2, element_id, comp_id, group_id, 0);
1422  mk_trc_h(fpout, name, grid_points[pt1], height, ro1, ro2);
1423  bu_free(name, "solid_name");
1424  } else {
1425  name = make_solid_name(CCONE2, element_id, comp_id, group_id, 1);
1426  mk_trc_h(fpout, name, grid_points[pt1], height, ro1, ro2);
1427 
1428  if (mk_addmember(name, &r_head.l, NULL, WMOP_UNION) == (struct wmember *)NULL)
1429  bu_exit(1, "mk_addmember failed!\n");
1430  bu_free(name, "solid_name");
1431 
1432  V_MAX(ri1, min_radius);
1433  V_MAX(ri2, min_radius);
1434 
1435  name = make_solid_name(CCONE2, element_id, comp_id, group_id, 2);
1436  mk_trc_h(fpout, name, grid_points[pt1], height, ri1, ri2);
1437 
1438  if (mk_addmember(name, &r_head.l, NULL, WMOP_SUBTRACT) == (struct wmember *)NULL)
1439  bu_exit(1, "mk_addmember failed!\n");
1440  bu_free(name, "solid_name");
1441 
1442  name = make_solid_name(CCONE2, element_id, comp_id, group_id, 0);
1443  mk_comb(fpout, name, &r_head.l, 0, NULL, NULL, NULL, 0, 0, 0, 0, 0, 1, 1);
1444  bu_free(name, "solid_name");
1445  }
1446 }
1447 
1448 
1449 static void
1450 f4_do_ccone3(void)
1451 {
1452  int element_id;
1453  int pt1, pt2, pt3, pt4, i;
1454  char *name;
1455  fastf_t ro[4], ri[4], len03, len01, len12, len23;
1456  vect_t diff, diff2, diff3, diff4;
1457  struct wmember r_head;
1458 
1459  bu_strlcpy(field, &line[8], sizeof(field));
1460  element_id = atoi(field);
1461 
1462  if (!pass) {
1463  make_region_name(group_id, comp_id);
1464  if (!get_line()) {
1465  bu_log("Unexpected EOF while reading continuation card for CCONE3\n");
1466  bu_log("\tgroup_id = %d, comp_id = %d, element_id = %d\n",
1467  group_id, comp_id, element_id);
1468  bu_exit(1, "ERROR: unexpected end-of-file encountered\n");
1469  }
1470  return;
1471  }
1472 
1473  bu_strlcpy(field, &line[24], sizeof(field));
1474  pt1 = atoi(field);
1475 
1476  bu_strlcpy(field, &line[32], sizeof(field));
1477  pt2 = atoi(field);
1478 
1479  bu_strlcpy(field, &line[40], sizeof(field));
1480  pt3 = atoi(field);
1481 
1482  bu_strlcpy(field, &line[48], sizeof(field));
1483  pt4 = atoi(field);
1484 
1485  bu_strlcpy(field, &line[72], sizeof(field));
1486 
1487  if (!get_line()) {
1488  bu_log("Unexpected EOF while reading continuation card for CCONE3\n");
1489  bu_log("\tgroup_id = %d, comp_id = %d, element_id = %d, c1 = %8.8s\n",
1490  group_id, comp_id, element_id, field);
1491  bu_exit(1, "ERROR: unexpected end-of-file encountered\n");
1492  }
1493 
1494  if (bu_strncmp(field, line, 8)) {
1495  bu_log("WARNING: CCONE3 continuation flags disagree, %8.8s vs %8.8s\n", field, line);
1496  bu_log("\tgroup_id = %d, comp_id = %d, element_id = %d\n",
1497  group_id, comp_id, element_id);
1498  }
1499 
1500  for (i=0; i<4; i++) {
1501  bu_strlcpy(field, &line[8*(i+1)], sizeof(field));
1502  ro[i] = atof(field) * 25.4;
1503  if (ro[i] < 0.0) {
1504  bu_log("ERROR: CCONE3 has illegal radius %f\n", ro[i]);
1505  bu_log("\tgroup_id = %d, comp_id = %d, element_id = %d\n",
1506  group_id, comp_id, element_id);
1507  return;
1508  }
1509  if (BU_STR_EQUAL(field, " "))
1510  ro[i] = -1.0;
1511  }
1512 
1513  for (i=0; i<4; i++) {
1514  bu_strlcpy(field, &line[32 + 8*(i+1)], sizeof(field));
1515  ri[i] = atof(field) * 25.4;
1516  if (ri[i] < 0.0) {
1517  bu_log("ERROR: CCONE3 has illegal radius %f\n", ri[i]);
1518  bu_log("\tgroup_id = %d, comp_id = %d, element_id = %d\n",
1519  group_id, comp_id, element_id);
1520  return;
1521  }
1522  if (BU_STR_EQUAL(field, " "))
1523  ri[i] = -1.0;
1524  }
1525 
1526  VSUB2(diff4, grid_points[pt4], grid_points[pt1]);
1527  VSUB2(diff3, grid_points[pt3], grid_points[pt1]);
1528  VSUB2(diff2, grid_points[pt2], grid_points[pt1]);
1529 
1530  len03 = MAGNITUDE(diff4);
1531  len01 = MAGNITUDE(diff2);
1532  len12 = MAGNITUDE(diff3) - len01;
1533  len23 = len03 - len01 - len12;
1534 
1535  for (i=0; i<4; i+=3) {
1536  if (EQUAL(ro[i], -1.0)) {
1537  if (EQUAL(ri[i], -1.0)) {
1538  bu_log("ERROR: both inner and outer radii at g%d of a CCONE3 are undefined\n", i+1);
1539  bu_log("\tgroup_id = %d, comp_id = %d, element_id = %d\n",
1540  group_id, comp_id, element_id);
1541  return;
1542  } else {
1543  ro[i] = ri[i];
1544  }
1545 
1546  } else if (EQUAL(ri[i], -1.0)) {
1547  ri[i] = ro[i];
1548  }
1549  }
1550 
1551  if (EQUAL(ro[1], -1.0)) {
1552  if (!EQUAL(ro[2], -1.0))
1553  ro[1] = ro[0] + (ro[2] - ro[0]) * len01 / (len01 + len12);
1554  else
1555  ro[1] = ro[0] + (ro[3] - ro[0]) * len01 / len03;
1556  }
1557  if (EQUAL(ro[2], -1.0)) {
1558  if (!EQUAL(ro[1], -1.0))
1559  ro[2] = ro[1] + (ro[3] - ro[1]) * len12 / (len12 + len23);
1560  else
1561  ro[2] = ro[0] + (ro[3] - ro[0]) * (len01 + len12) / len03;
1562  }
1563  if (EQUAL(ri[1], -1.0)) {
1564  if (!EQUAL(ri[2], -1.0))
1565  ri[1] = ri[0] + (ri[2] - ri[0]) * len01 / (len01 + len12);
1566  else
1567  ri[1] = ri[0] + (ri[3] - ri[0]) * len01 / len03;
1568  }
1569  if (EQUAL(ri[2], -1.0)) {
1570  if (!EQUAL(ri[1], -1.0))
1571  ri[2] = ri[1] + (ri[3] - ri[1]) * len12 / (len12 + len23);
1572  else
1573  ri[2] = ri[0] + (ri[3] - ri[0]) * (len01 + len12) / len03;
1574  }
1575 
1576  for (i=0; i<4; i++) {
1577  V_MAX(ro[i], min_radius);
1578  V_MAX(ri[i], min_radius);
1579  }
1580 
1581  BU_LIST_INIT(&r_head.l);
1582 
1583  if (pt1 != pt2) {
1584  VSUB2(diff, grid_points[pt2], grid_points[pt1]);
1585 
1586  /* make first cone */
1587  if (!EQUAL(ro[0], min_radius) || !EQUAL(ro[1], min_radius)) {
1588  name = make_solid_name(CCONE3, element_id, comp_id, group_id, 1);
1589  mk_trc_h(fpout, name, grid_points[pt1], diff, ro[0], ro[1]);
1590  if (mk_addmember(name, &r_head.l, NULL, WMOP_UNION) == (struct wmember *)NULL)
1591  bu_exit(1, "mk_addmember failed!\n");
1592  bu_free(name, "solid_name");
1593 
1594  /* and the inner cone */
1595  if (!EQUAL(ri[0], min_radius) || !EQUAL(ri[1], min_radius)) {
1596  name = make_solid_name(CCONE3, element_id, comp_id, group_id, 11);
1597  mk_trc_h(fpout, name, grid_points[pt1], diff, ri[0], ri[1]);
1598  if (mk_addmember(name, &r_head.l, NULL, WMOP_SUBTRACT) == (struct wmember *)NULL)
1599  bu_exit(1, "mk_addmember failed!\n");
1600  bu_free(name, "solid_name");
1601  }
1602  }
1603  }
1604 
1605  if (pt2 != pt3) {
1606  VSUB2(diff, grid_points[pt3], grid_points[pt2]);
1607 
1608  /* make second cone */
1609  if (!EQUAL(ro[1], min_radius) || !EQUAL(ro[2], min_radius)) {
1610  name = make_solid_name(CCONE3, element_id, comp_id, group_id, 2);
1611  mk_trc_h(fpout, name, grid_points[pt2], diff, ro[1], ro[2]);
1612  if (mk_addmember(name, &r_head.l, NULL, WMOP_UNION) == (struct wmember *)NULL)
1613  bu_exit(1, "mk_addmember failed!\n");
1614  bu_free(name, "solid_name");
1615 
1616  /* and the inner cone */
1617  if (!EQUAL(ri[1], min_radius) || !EQUAL(ri[2], min_radius)) {
1618  name = make_solid_name(CCONE3, element_id, comp_id, group_id, 22);
1619  mk_trc_h(fpout, name, grid_points[pt2], diff, ri[1], ri[2]);
1620  if (mk_addmember(name, &r_head.l, NULL, WMOP_SUBTRACT) == (struct wmember *)NULL)
1621  bu_exit(1, "mk_addmember failed!\n");
1622  bu_free(name, "solid_name");
1623  }
1624  }
1625  }
1626 
1627  if (pt3 != pt4) {
1628  VSUB2(diff, grid_points[pt4], grid_points[pt3]);
1629 
1630  /* make third cone */
1631  if (!EQUAL(ro[2], min_radius) || !EQUAL(ro[3], min_radius)) {
1632  name = make_solid_name(CCONE3, element_id, comp_id, group_id, 3);
1633  mk_trc_h(fpout, name, grid_points[pt3], diff, ro[2], ro[3]);
1634  if (mk_addmember(name, &r_head.l, NULL, WMOP_UNION) == (struct wmember *)NULL)
1635  bu_exit(1, "mk_addmember failed!\n");
1636  bu_free(name, "solid_name");
1637 
1638  /* and the inner cone */
1639  if (!EQUAL(ri[2], min_radius) || !EQUAL(ri[3], min_radius)) {
1640  name = make_solid_name(CCONE3, element_id, comp_id, group_id, 33);
1641  mk_trc_h(fpout, name, grid_points[pt3], diff, ri[2], ri[3]);
1642  if (mk_addmember(name, &r_head.l, NULL, WMOP_SUBTRACT) == (struct wmember *)NULL)
1643  bu_exit(1, "mk_addmember failed!\n");
1644  bu_free(name, "solid_name");
1645  }
1646  }
1647  }
1648 
1649  name = make_solid_name(CCONE3, element_id, comp_id, group_id, 0);
1650  mk_comb(fpout, name, &r_head.l, 0, NULL, NULL, NULL, 0, 0, 0, 0, 0, 1, 1);
1651  bu_free(name, "solid_name");
1652 }
1653 
1654 
1655 static int
1656 skip_region(int id)
1657 {
1658  int i;
1659 
1660  if (!f4_do_skips)
1661  return 0;
1662 
1663  for (i=0; i<f4_do_skips; i++) {
1664  if (id == region_list[i])
1665  return 0;
1666  }
1667 
1668  return 1;
1669 }
1670 
1671 
1672 static void
1673 Add_holes(int type, int gr, int comp, struct hole_list *ptr)
1674 {
1675  struct holes *hole_ptr = (struct holes *)NULL;
1676  struct holes *prev = (struct holes *)NULL;
1677  struct hole_list *hptr= (struct hole_list *)NULL;
1678 
1679  if (debug) {
1680  bu_log("Adding holes for group %d, component %d:\n", gr, comp);
1681  hptr = ptr;
1682  while (hptr) {
1683  bu_log("\t%d %d\n", hptr->group, hptr->component);
1684  hptr = hptr->next;
1685  }
1686  }
1687 
1688  if (f4_do_skips) {
1689  if (!skip_region(gr*1000 + comp)) {
1690  /* add holes for this region to the list of regions to process */
1691  hptr = ptr;
1693  bu_log("ERROR: bu_mem_barriercheck failed in Add_hole\n");
1694  while (hptr) {
1695  if (f4_do_skips == region_list_len) {
1696  region_list_len += REGION_LIST_BLOCK;
1697  region_list = (int *)bu_realloc((char *)region_list, region_list_len*sizeof(int), "region_list");
1699  bu_log("ERROR: bu_mem_barriercheck failed in Add_hole (after realloc)\n");
1700  }
1701  region_list[f4_do_skips++] = 1000*hptr->group + hptr->component;
1703  bu_log("ERROR: bu_mem_barriercheck failed in Add_hole (after adding %d\n)\n", 1000*hptr->group + hptr->component);
1704  hptr = hptr->next;
1705  }
1706  }
1707  }
1708 
1709  if (!hole_root) {
1710  BU_ALLOC(hole_root, struct holes);
1711  hole_root->group = gr;
1712  hole_root->component = comp;
1713  hole_root->type = type;
1714  hole_root->holes = ptr;
1715  hole_root->next = (struct holes *)NULL;
1716  return;
1717  }
1718 
1719  hole_ptr = hole_root;
1720  prev = hole_root;
1721  while (hole_ptr) {
1722  if (hole_ptr->group == gr &&
1723  hole_ptr->component == comp &&
1724  hole_ptr->type == type)
1725  break;
1726  prev = hole_ptr;
1727  hole_ptr = hole_ptr->next;
1728  }
1729 
1730  if (hole_ptr && hole_ptr->group == gr && hole_ptr->component == comp && hole_ptr->type == type) {
1731  struct hole_list *list;
1732 
1733  if (!hole_ptr->holes) {
1734  hole_ptr->holes = ptr;
1735  } else {
1736  list = hole_ptr->holes;
1737  while (list->next)
1738  list = list->next;
1739  list->next = ptr;
1740  }
1741  } else {
1742  BU_ALLOC(prev->next, struct holes);
1743  hole_ptr = prev->next;
1744  hole_ptr->group = gr;
1745  hole_ptr->component = comp;
1746  hole_ptr->type = type;
1747  hole_ptr->holes = ptr;
1748  hole_ptr->next = (struct holes *)NULL;
1749  }
1750 }
1751 
1752 
1753 static void
1754 f4_do_hole_wall(int type)
1755 {
1756  struct hole_list *list_ptr;
1757  struct hole_list *list_start;
1758  int group, comp;
1759  int igrp, icmp;
1760  size_t s_len;
1761  size_t col;
1762 
1763  if (debug)
1764  bu_log("f4_do_hole_wall: %s\n", line);
1765 
1766  if (pass)
1767  return;
1768 
1769  if (type != HOLE && type != WALL) {
1770  bu_exit(1, "f4_do_hole_wall: unrecognized type (%d)\n", type);
1771  }
1772 
1773  /* eliminate trailing blanks */
1774  s_len = strlen(line);
1775  while (isspace((int)line[--s_len]))
1776  line[s_len] = '\0';
1777 
1778  s_len = strlen(line);
1779  V_MIN(s_len, 80);
1780 
1781  bu_strlcpy(field, &line[8], sizeof(field));
1782  group = atoi(field);
1783 
1784  bu_strlcpy(field, &line[16], sizeof(field));
1785  comp = atoi(field);
1786 
1787  list_start = (struct hole_list *)NULL;
1788  list_ptr = (struct hole_list *)NULL;
1789  col = 24;
1790 
1791  while (col < s_len) {
1792  bu_strlcpy(field, &line[col], sizeof(field));
1793  igrp = atoi(field);
1794 
1795  col += 8;
1796  if (col >= s_len)
1797  break;
1798 
1799  bu_strlcpy(field, &line[col], sizeof(field));
1800  icmp = atoi(field);
1801 
1802  if (igrp >= 0 && icmp > 0) {
1803  if (igrp == group && comp == icmp) {
1804  bu_log("Hole or wall card references itself (ignoring): (%s)\n", line);
1805  } else {
1806  if (list_ptr) {
1807  BU_ALLOC(list_ptr->next, struct hole_list);
1808  list_ptr = list_ptr->next;
1809  } else {
1810  BU_ALLOC(list_ptr, struct hole_list);
1811  list_start = list_ptr;
1812  }
1813 
1814  list_ptr->group = igrp;
1815  list_ptr->component = icmp;
1816  list_ptr->next = (struct hole_list *)NULL;
1817  }
1818  }
1819 
1820  col += 8;
1821  }
1822 
1823  Add_holes(type, group, comp, list_start);
1824 }
1825 
1826 
1827 static void
1828 f4_Add_bot_face(int pt1, int pt2, int pt3, fastf_t thick, int pos)
1829 {
1830 
1831  if (pt1 == pt2 || pt2 == pt3 || pt1 == pt3) {
1832  bu_log("f4_Add_bot_face: ignoring degenerate triangle in group %d component %d\n", group_id, comp_id);
1833  return;
1834  }
1835 
1836  if (pos == 0) /* use default */
1837  pos = POS_FRONT;
1838 
1839  if (mode == PLATE_MODE) {
1840  if (pos != POS_CENTER && pos != POS_FRONT) {
1841  bu_log("f4_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);
1842  return;
1843  }
1844  }
1845 
1846  if (face_count >= face_size) {
1847  face_size += GRID_BLOCK;
1849  bu_log("memory corrupted before realloc of faces, thickness, and facemode\n");
1850  faces = (int *)bu_realloc((void *)faces, face_size*3*sizeof(int), "faces");
1851  thickness = (fastf_t *)bu_realloc((void *)thickness, face_size*sizeof(fastf_t), "thickness");
1852  facemode = (char *)bu_realloc((void *)facemode, face_size*sizeof(char), "facemode");
1854  bu_log("memory corrupted after realloc of faces, thickness, and facemode\n");
1855  }
1856 
1857  faces[face_count*3] = pt1;
1858  faces[face_count*3+1] = pt2;
1859  faces[face_count*3+2] = pt3;
1860 
1861  if (mode == PLATE_MODE) {
1862  thickness[face_count] = thick;
1863  facemode[face_count] = pos;
1864  } else {
1865  thickness[face_count] = 0.0;
1866  facemode[face_count] = 0;
1867  }
1868 
1869  face_count++;
1870 
1872  bu_log("memory corrupted at end of f4_Add_bot_face()\n");
1873 }
1874 
1875 
1876 static void
1877 f4_do_tri(void)
1878 {
1879  int element_id;
1880  int pt1, pt2, pt3;
1881  fastf_t thick;
1882  int pos;
1883 
1884  if (debug)
1885  bu_log("f4_do_tri: %s\n", line);
1886 
1887  bu_strlcpy(field, &line[8], sizeof(field));
1888  element_id = atoi(field);
1889 
1890  if (!bot)
1891  bot = element_id;
1892 
1893  if (!pass)
1894  return;
1895 
1896  if (faces == NULL) {
1898  bu_log("memory corrupted before malloc of faces\n");
1899  faces = (int *)bu_malloc(GRID_BLOCK*3*sizeof(int), "faces");
1900  thickness = (fastf_t *)bu_malloc(GRID_BLOCK*sizeof(fastf_t), "thickness");
1901  facemode = (char *)bu_malloc(GRID_BLOCK*sizeof(char), "facemode");
1902  face_size = GRID_BLOCK;
1903  face_count = 0;
1905  bu_log("memory corrupted after malloc of faces, thickness, and facemode\n");
1906  }
1907 
1908  bu_strlcpy(field, &line[24], sizeof(field));
1909  pt1 = atoi(field);
1910 
1911  bu_strlcpy(field, &line[32], sizeof(field));
1912  pt2 = atoi(field);
1913 
1914  bu_strlcpy(field, &line[40], sizeof(field));
1915  pt3 = atoi(field);
1916 
1917  thick = 0.0;
1918  pos = 0;
1919 
1920  if (mode == PLATE_MODE) {
1921  bu_strlcpy(field, &line[56], sizeof(field));
1922  thick = atof(field) * 25.4;
1923 
1924  bu_strlcpy(field, &line[64], sizeof(field));
1925  pos = atoi(field);
1926  if (pos == 0)
1927  pos = POS_FRONT;
1928 
1929  if (debug)
1930  bu_log("\tplate mode: thickness = %f\n", thick);
1931 
1932  }
1933 
1934  if (f4_do_plot)
1935  plot_tri(pt1, pt2, pt3);
1936 
1938  bu_log("memory corrupted before call to f4_Add_bot_face()\n");
1939 
1940  f4_Add_bot_face(pt1, pt2, pt3, thick, pos);
1941 
1943  bu_log("memory corrupted after call to f4_Add_bot_face()\n");
1944 }
1945 
1946 
1947 static void
1948 f4_do_quad(void)
1949 {
1950  int element_id;
1951  int pt1, pt2, pt3, pt4;
1952  fastf_t thick = 0.0;
1953  int pos = 0;
1954 
1955  bu_strlcpy(field, &line[8], sizeof(field));
1956  element_id = atoi(field);
1957 
1958  if (debug)
1959  bu_log("f4_do_quad: %s\n", line);
1960 
1961  if (!bot)
1962  bot = element_id;
1963 
1964  if (!pass)
1965  return;
1966 
1967  if (faces == NULL) {
1968  faces = (int *)bu_malloc(GRID_BLOCK*3*sizeof(int), "faces");
1969  thickness = (fastf_t *)bu_malloc(GRID_BLOCK*sizeof(fastf_t), "thickness");
1970  facemode = (char *)bu_malloc(GRID_BLOCK*sizeof(char), "facemode");
1971  face_size = GRID_BLOCK;
1972  face_count = 0;
1973  }
1974 
1975  bu_strlcpy(field, &line[24], sizeof(field));
1976  pt1 = atoi(field);
1977 
1978  bu_strlcpy(field, &line[32], sizeof(field));
1979  pt2 = atoi(field);
1980 
1981  bu_strlcpy(field, &line[40], sizeof(field));
1982  pt3 = atoi(field);
1983 
1984  bu_strlcpy(field, &line[48], sizeof(field));
1985  pt4 = atoi(field);
1986 
1987  if (mode == PLATE_MODE) {
1988  bu_strlcpy(field, &line[56], sizeof(field));
1989  thick = atof(field) * 25.4;
1990 
1991  bu_strlcpy(field, &line[64], sizeof(field));
1992  pos = atoi(field);
1993 
1994  if (pos == 0) /* use default */
1995  pos = POS_FRONT;
1996 
1997  if (pos != POS_CENTER && pos != POS_FRONT) {
1998  bu_log("f4_do_quad: illegal position parameter (%d), must be one or two\n", pos);
1999  bu_log("\telement %d, component %d, group %d\n", element_id, comp_id, group_id);
2000  return;
2001  }
2002  }
2003 
2004  f4_Add_bot_face(pt1, pt2, pt3, thick, pos);
2005  f4_Add_bot_face(pt1, pt3, pt4, thick, pos);
2006 }
2007 
2008 
2009 static void
2010 make_bot_object(void)
2011 {
2012  int i;
2013  int max_pt = 0;
2014  int min_pt = 999999;
2015  int num_vertices;
2016  struct bu_bitv *bv = (struct bu_bitv *)NULL;
2017  int bot_mode;
2018  char *name = (char *)NULL;
2019  int element_id = bot;
2020  int count;
2021  struct rt_bot_internal bot_ip;
2022 
2023  if (!pass) {
2024  make_region_name(group_id, comp_id);
2025  return;
2026  }
2027 
2028  bot_ip.magic = RT_BOT_INTERNAL_MAGIC;
2029  for (i=0; i<face_count; i++) {
2030  V_MIN(min_pt, faces[i*3]);
2031  V_MAX(max_pt, faces[i*3]);
2032  V_MIN(min_pt, faces[i*3+1]);
2033  V_MAX(max_pt, faces[i*3+1]);
2034  V_MIN(min_pt, faces[i*3+2]);
2035  V_MAX(max_pt, faces[i*3+2]);
2036  }
2037 
2038  num_vertices = max_pt - min_pt + 1;
2039  bot_ip.num_vertices = num_vertices;
2040  bot_ip.vertices = (fastf_t *)bu_calloc(num_vertices*3, sizeof(fastf_t), "BOT vertices");
2041  for (i=0; i<num_vertices; i++)
2042  VMOVE(&bot_ip.vertices[i*3], grid_points[min_pt+i]);
2043 
2044  for (i=0; i<face_count*3; i++)
2045  faces[i] -= min_pt;
2046  bot_ip.num_faces = face_count;
2047  bot_ip.faces = (int *)bu_calloc(face_count*3, sizeof(int), "BOT faces");
2048  for (i=0; i<face_count*3; i++)
2049  bot_ip.faces[i] = faces[i];
2050 
2051  bot_ip.face_mode = (struct bu_bitv *)NULL;
2052  bot_ip.thickness = (fastf_t *)NULL;
2053  if (mode == PLATE_MODE) {
2054  bot_mode = RT_BOT_PLATE;
2055  bv = bu_bitv_new(face_count);
2056  for (i=0; i<face_count; i++) {
2057  if (facemode[i] == POS_FRONT)
2058  BU_BITSET(bv, i);
2059  }
2060  bot_ip.face_mode = bv;
2061  bot_ip.thickness = (fastf_t *)bu_calloc(face_count, sizeof(fastf_t), "BOT thickness");
2062  for (i=0; i<face_count; i++)
2063  bot_ip.thickness[i] = thickness[i];
2064  } else {
2065  bot_mode = RT_BOT_SOLID;
2066  }
2067 
2068  bot_ip.mode = bot_mode;
2069  bot_ip.orientation = RT_BOT_UNORIENTED;
2070  bot_ip.bot_flags = 0;
2071 
2072  count = rt_bot_vertex_fuse(&bot_ip, &fpout->wdb_tol);
2073  count = rt_bot_face_fuse(&bot_ip);
2074  if (count)
2075  bu_log("WARNING: %d duplicate faces eliminated from group %d component %d\n", count, group_id, comp_id);
2076 
2077  name = make_solid_name(BOT, element_id, comp_id, group_id, 0);
2078  mk_bot(fpout, name, bot_mode, RT_BOT_UNORIENTED, 0, bot_ip.num_vertices, bot_ip.num_faces, bot_ip.vertices,
2079  bot_ip.faces, bot_ip.thickness, bot_ip.face_mode);
2080  bu_free(name, "solid_name");
2081 
2082  if (mode == PLATE_MODE) {
2083  bu_free((char *)bot_ip.thickness, "BOT thickness");
2084  bu_free((char *)bot_ip.face_mode, "BOT face_mode");
2085  }
2086  bu_free((char *)bot_ip.vertices, "BOT vertices");
2087  bu_free((char *)bot_ip.faces, "BOT faces");
2088 
2089 }
2090 
2091 
2092 static void
2093 skip_section(void)
2094 {
2095  off_t section_start;
2096 
2097  /* skip to start of next section */
2098  section_start = bu_ftell(fpin);
2099  if (section_start < 0) {
2100  bu_exit(1, "Error: couldn't get input file's current file position.\n");
2101  }
2102 
2103  if (get_line()) {
2104  while (line[0] && bu_strncmp(line, "SECTION", 7) &&
2105  bu_strncmp(line, "HOLE", 4) &&
2106  bu_strncmp(line, "WALL", 4) &&
2107  bu_strncmp(line, "VEHICLE", 7))
2108  {
2109  section_start = bu_ftell(fpin);
2110  if (section_start < 0) {
2111  bu_exit(1, "Error: couldn't get input file's current file position.\n");
2112  }
2113  if (!get_line())
2114  break;
2115  }
2116  }
2117  /* seek to start of the section */
2118  bu_fseek(fpin, section_start, SEEK_SET);
2119 }
2120 
2121 
2122 /* cleanup from previous component and start a new one.
2123  * This is called with final == 1 when ENDDATA is found
2124  */
2125 static void
2126 f4_do_section(int final)
2127 {
2128  int found;
2129  struct name_tree *nm_ptr;
2130 
2131  if (debug)
2132  bu_log("f4_do_section(%d): %s\n", final, line);
2133 
2134  if (pass) /* doing geometry */ {
2135  if (region_id && !skip_region(region_id)) {
2136  comp_count++;
2137 
2138  if (bot)
2139  make_bot_object();
2140  }
2141  if (final && debug) /* The ENDATA card has been found */
2142  List_names();
2143  } else if (bot) {
2144  make_region_name(group_id, comp_id);
2145  }
2146 
2147  if (!final) {
2148  bu_strlcpy(field, &line[8], sizeof(field));
2149  group_id = atoi(field);
2150 
2151  bu_strlcpy(field, &line[16], sizeof(field));
2152  comp_id = atoi(field);
2153 
2154  region_id = group_id * 1000 + comp_id;
2155 
2156  if (skip_region(region_id)) /* do not process this component */ {
2157  skip_section();
2158  return;
2159  }
2160 
2161  if (comp_id > 999) {
2162  bu_log("Illegal component id number %d, changed to 999\n", comp_id);
2163  comp_id = 999;
2164  }
2165 
2166  bu_strlcpy(field, &line[24], sizeof(field));
2167  mode = atoi(field);
2168  if (mode != 1 && mode != 2) {
2169  bu_log("Illegal mode (%d) for group %d component %d, using volume mode\n",
2170  mode, group_id, comp_id);
2171  mode = 2;
2172  }
2173 
2174  if (!pass) {
2175  nm_ptr = Search_ident(name_root, region_id, &found);
2176  if (found && nm_ptr->mode != mode) {
2177  bu_log("ERROR: second SECTION card found with different mode for component (group=%d, component=%d), conversion of this component will be incorrect!\n",
2178  group_id, comp_id);
2179  }
2180  }
2181  }
2182 
2183  bot = 0;
2184  face_count = 0;
2185 }
2186 
2187 
2188 static void
2189 f4_do_hex1(void)
2190 {
2191  fastf_t thick=0.0;
2192  int pos;
2193  int pts[8];
2194  int element_id;
2195  int i;
2196  int cont1, cont2;
2197 
2198  bu_strlcpy(field, &line[8], sizeof(field));
2199  element_id = atoi(field);
2200 
2201  if (!bot)
2202  bot = element_id;
2203 
2204  if (!pass) {
2205  if (!get_line()) {
2206  bu_log("Unexpected EOF while reading continuation card for CHEX1\n");
2207  bu_log("\tgroup_id = %d, comp_id = %d, element_id = %d\n",
2208  group_id, comp_id, element_id);
2209  bu_exit(1, "ERROR: unexpected end-of-file encountered\n");
2210  }
2211  return;
2212  }
2213 
2214  if (faces == NULL) {
2215  faces = (int *)bu_malloc(GRID_BLOCK*3*sizeof(int), "faces");
2216  thickness = (fastf_t *)bu_malloc(GRID_BLOCK*sizeof(fastf_t), "thickness");
2217  facemode = (char *)bu_malloc(GRID_BLOCK*sizeof(char), "facemode");
2218  face_size = GRID_BLOCK;
2219  face_count = 0;
2220  }
2221 
2222  for (i=0; i<6; i++) {
2223  bu_strlcpy(field, &line[24 + i*8], sizeof(field));
2224  pts[i] = atoi(field);
2225  }
2226 
2227  bu_strlcpy(field, &line[72], sizeof(field));
2228  cont1 = atoi(field);
2229 
2230  if (!get_line()) {
2231  bu_log("Unexpected EOF while reading continuation card for CHEX1\n");
2232  bu_log("\tgroup_id = %d, comp_id = %d, element_id = %d, c1 = %d\n",
2233  group_id, comp_id, element_id, cont1);
2234  bu_exit(1, "ERROR: unexpected end-of-file encountered\n");
2235  }
2236 
2237  bu_strlcpy(field, line, sizeof(field));
2238  cont2 = atoi(field);
2239 
2240  if (cont1 != cont2) {
2241  bu_log("Continuation card numbers do not match for CHEX1 element (%d vs %d)\n", cont1, cont2);
2242  bu_log("\tskipping CHEX1 element: group_id = %d, comp_id = %d, element_id = %d\n",
2243  group_id, comp_id, element_id);
2244  return;
2245  }
2246 
2247  bu_strlcpy(field, &line[8], sizeof(field));
2248  pts[6] = atoi(field);
2249 
2250  bu_strlcpy(field, &line[16], sizeof(field));
2251  pts[7] = atoi(field);
2252 
2253  if (mode == PLATE_MODE) {
2254  bu_strlcpy(field, &line[56], sizeof(field));
2255  thick = atof(field) * 25.4;
2256  if (thick <= 0.0) {
2257  bu_log("f4_do_hex1: illegal thickness (%f), skipping CHEX1 element\n", thick);
2258  bu_log("\telement %d, component %d, group %d\n", element_id, comp_id, group_id);
2259  return;
2260  }
2261 
2262  bu_strlcpy(field, &line[64], sizeof(field));
2263  pos = atoi(field);
2264 
2265  if (pos == 0) /* use default */
2266  pos = POS_FRONT;
2267 
2268  if (pos != POS_CENTER && pos != POS_FRONT) {
2269  bu_log("f4_do_hex1: illegal position parameter (%d), must be 1 or 2, skipping CHEX1 element\n", pos);
2270  bu_log("\telement %d, component %d, group %d\n", element_id, comp_id, group_id);
2271  return;
2272  }
2273  } else {
2274  pos = POS_FRONT;
2275  thick = 0.0;
2276  }
2277 
2278  for (i=0; i<12; i++)
2279  f4_Add_bot_face(pts[hex_faces[i][0]], pts[hex_faces[i][1]], pts[hex_faces[i][2]], thick, pos);
2280 }
2281 
2282 
2283 static void
2284 f4_do_hex2(void)
2285 {
2286  int pts[8];
2287  int element_id;
2288  int i;
2289  int cont1, cont2;
2290  point_t points[8];
2291  char *name = (char *)NULL;
2292 
2293  bu_strlcpy(field, &line[8], sizeof(field));
2294  element_id = atoi(field);
2295 
2296  if (!pass) {
2297  make_region_name(group_id, comp_id);
2298  if (!get_line()) {
2299  bu_log("Unexpected EOF while reading continuation card for CHEX2\n");
2300  bu_log("\tgroup_id = %d, comp_id = %d, element_id = %d\n",
2301  group_id, comp_id, element_id);
2302  bu_exit(1, "ERROR: unexpected end-of-file encountered\n");
2303  }
2304  return;
2305  }
2306 
2307  for (i=0; i<6; i++) {
2308  bu_strlcpy(field, &line[24 + i*8], sizeof(field));
2309  pts[i] = atoi(field);
2310  }
2311 
2312  bu_strlcpy(field, &line[72], sizeof(field));
2313  cont1 = atoi(field);
2314 
2315  if (!get_line()) {
2316  bu_log("Unexpected EOF while reading continuation card for CHEX2\n");
2317  bu_log("\tgroup_id = %d, comp_id = %d, element_id = %d, c1 = %d\n",
2318  group_id, comp_id, element_id, cont1);
2319  bu_exit(1, "ERROR: unexpected end-of-file encountered\n");
2320  }
2321 
2322  bu_strlcpy(field, line, sizeof(field));
2323  cont2 = atoi(field);
2324 
2325  if (cont1 != cont2) {
2326  bu_log("Continuation card numbers do not match for CHEX2 element (%d vs %d)\n", cont1, cont2);
2327  bu_log("\tskipping CHEX2 element: group_id = %d, comp_id = %d, element_id = %d\n",
2328  group_id, comp_id, element_id);
2329  return;
2330  }
2331 
2332  bu_strlcpy(field, &line[8], sizeof(field));
2333  pts[6] = atoi(field);
2334 
2335  bu_strlcpy(field, &line[16], sizeof(field));
2336  pts[7] = atoi(field);
2337 
2338  for (i=0; i<8; i++)
2339  VMOVE(points[i], grid_points[pts[i]]);
2340 
2341  name = make_solid_name(CHEX2, element_id, comp_id, group_id, 0);
2342  mk_arb8(fpout, name, &points[0][X]);
2343  bu_free(name, "solid_name");
2344 
2345 }
2346 
2347 
2348 static void
2349 Process_hole_wall(void)
2350 {
2351  if (debug)
2352  bu_log("Process_hole_wall\n");
2354  bu_prmem("At start of Process_hole_wall:");
2355 
2356  rewind(fpin);
2357  while (1) {
2358  if (!bu_strncmp(line, "HOLE", 4)) {
2359  f4_do_hole_wall(HOLE);
2360  } else if (!bu_strncmp(line, "WALL", 4)) {
2361  f4_do_hole_wall(WALL);
2362  } else if (!bu_strncmp(line, "COMPSPLT", 8)) {
2363  f4_do_compsplt();
2364  } else if (!bu_strncmp(line, "SECTION", 7)) {
2365  bu_strlcpy(field, &line[24], sizeof(field));
2366  mode = atoi(field);
2367  if (mode != 1 && mode != 2) {
2368  bu_log("Illegal mode (%d) for group %d component %d, using volume mode\n",
2369  mode, group_id, comp_id);
2370  mode = 2;
2371  }
2372  } else if (!bu_strncmp(line, "ENDDATA", 7)) {
2373  break;
2374  }
2375 
2376  if (!get_line() || !line[0])
2377  break;
2378  }
2379 
2380  if (debug) {
2381  bu_log("At end of Process_hole_wall:\n");
2382  List_holes();
2383  }
2384 }
2385 
2386 
2387 static void
2388 f4_do_chgcomp(void)
2389 {
2390 
2391  if (!pass)
2392  return;
2393 
2394  if (!fp_muves)
2395  return;
2396 
2397  fprintf(fp_muves, "%s", line);
2398 }
2399 
2400 
2401 static void
2402 f4_do_cbacking(void)
2403 {
2404  int gr1, co1, gr2, co2, material;
2405  fastf_t inthickness, probability;
2406 
2407  if (!pass)
2408  return;
2409 
2410  if (!fp_muves)
2411  return;
2412 
2413  bu_strlcpy(field, &line[8], sizeof(field));
2414  gr1 = atoi(field);
2415 
2416  bu_strlcpy(field, &line[16], sizeof(field));
2417  co1 = atoi(field);
2418 
2419  bu_strlcpy(field, &line[24], sizeof(field));
2420  gr2 = atoi(field);
2421 
2422  bu_strlcpy(field, &line[32], sizeof(field));
2423  co2 = atoi(field);
2424 
2425  bu_strlcpy(field, &line[40], sizeof(field));
2426  inthickness = atof(field) * 25.4;
2427 
2428  bu_strlcpy(field, &line[48], sizeof(field));
2429  probability = atof(field);
2430 
2431  bu_strlcpy(field, &line[56], sizeof(field));
2432  material = atoi(field);
2433 
2434  fprintf(fp_muves, "CBACKING %d %d %g %g %d\n", gr1*1000+co1, gr2*1000+co2, inthickness, probability, material);
2435 }
2436 
2437 
2438 static int
2439 Process_input(int pass_number)
2440 {
2441 
2442  if (debug)
2443  bu_log("\n\nProcess_input(pass = %d)\n", pass_number);
2444  if (bu_debug & BU_DEBUG_MEM_CHECK)
2445  bu_prmem("At start of Process_input:");
2446 
2447  if (pass_number != 0 && pass_number != 1) {
2448  bu_exit(1, "Process_input: illegal pass number %d\n", pass_number);
2449  }
2450 
2451  region_id = 0;
2452  pass = pass_number;
2453  if (!get_line() || !line[0])
2454  bu_strlcpy(line, "ENDDATA", sizeof(line));
2455  while (1) {
2456  if (!bu_strncmp(line, "VEHICLE", 7))
2457  f4_do_vehicle();
2458  else if (!bu_strncmp(line, "HOLE", 4))
2459  ;
2460  else if (!bu_strncmp(line, "WALL", 4))
2461  ;
2462  else if (!bu_strncmp(line, "COMPSPLT", 8))
2463  ;
2464  else if (!bu_strncmp(line, "CBACKING", 8))
2465  f4_do_cbacking();
2466  else if (!bu_strncmp(line, "CHGCOMP", 7))
2467  f4_do_chgcomp();
2468  else if (!bu_strncmp(line, "SECTION", 7))
2469  f4_do_section(0);
2470  else if (!bu_strncmp(line, "$NAME", 5))
2471  f4_do_name();
2472  else if (!bu_strncmp(line, "$COMMENT", 8))
2473  ;
2474  else if (!bu_strncmp(line, "GRID", 4))
2475  f4_do_grid();
2476  else if (!bu_strncmp(line, "CLINE", 5))
2477  f4_do_cline();
2478  else if (!bu_strncmp(line, "CHEX1", 5))
2479  f4_do_hex1();
2480  else if (!bu_strncmp(line, "CHEX2", 5))
2481  f4_do_hex2();
2482  else if (!bu_strncmp(line, "CTRI", 4))
2483  f4_do_tri();
2484  else if (!bu_strncmp(line, "CQUAD", 5))
2485  f4_do_quad();
2486  else if (!bu_strncmp(line, "CCONE1", 6))
2487  f4_do_ccone1();
2488  else if (!bu_strncmp(line, "CCONE2", 6))
2489  f4_do_ccone2();
2490  else if (!bu_strncmp(line, "CCONE3", 6))
2491  f4_do_ccone3();
2492  else if (!bu_strncmp(line, "CSPHERE", 7))
2493  f4_do_sphere();
2494  else if (!bu_strncmp(line, "ENDDATA", 7)) {
2495  f4_do_section(1);
2496  break;
2497  } else {
2498  bu_log("ERROR: skipping unrecognized data type\n%s\n", line);
2499  }
2500 
2501  if (!get_line() || !line[0])
2502  bu_strlcpy(line, "ENDDATA", sizeof(line));
2503  }
2504 
2505  if (debug) {
2506  bu_log("At pass %d:\n", pass);
2507  List_names();
2508  }
2509 
2510  return 0;
2511 }
2512 
2513 
2514 static void
2515 make_regions(void)
2516 {
2517  struct name_tree *ptr1, *ptr2;
2518  struct holes *hptr;
2519  struct hole_list *lptr;
2520  struct compsplt *splt;
2521  struct wmember region;
2522  struct wmember solids;
2523  struct wmember holes;
2524  char reg_name[MAX_LINE_SIZE] = {0};
2525  char solids_name[MAX_LINE_SIZE] = {0};
2526  char hole_name[MAX_LINE_SIZE] = {0};
2527  char splt_name[MAX_LINE_SIZE] = {0};
2528 
2529  BU_LIST_INIT(&holes.l);
2530 
2531  /* loop through the list of region names (by ident) */
2532  bu_ptbl_reset(&stack);
2533  ptr1 = name_root;
2534  while (1) {
2535  while (ptr1) {
2536  PUSH(ptr1);
2537  ptr1 = ptr1->rleft;
2538  }
2539  POP(name_tree, ptr1);
2540  if (!ptr1)
2541  break;
2542 
2543  /* check if we are skipping some regions (but we might need all the holes) */
2544  if (skip_region(ptr1->region_id) && !is_a_hole(ptr1->region_id))
2545  goto cont1;
2546 
2547  /* place all the solids for this ident in a "solids" combination */
2548  BU_LIST_INIT(&solids.l);
2549  bu_ptbl_reset(&stack2);
2550  ptr2 = name_root;
2551  while (1) {
2552  while (ptr2) {
2553  PUSH2(ptr2);
2554  ptr2 = ptr2->nleft;
2555  }
2556  POP2(name_tree, ptr2);
2557  if (!ptr2)
2558  break;
2559 
2560  if (ptr2->region_id == -ptr1->region_id && ptr2->inner == 0) {
2561  if (mk_addmember(ptr2->name, &solids.l, NULL, WMOP_UNION) == (struct wmember *)NULL)
2562  bu_log("make_regions: mk_addmember failed to add %s to %s\n", ptr1->name, ptr2->name);
2563  }
2564 
2565  ptr2 = ptr2->nright;
2566  }
2567 
2568  if (BU_LIST_IS_EMPTY(&solids.l))
2569  goto cont1;
2570 
2571  snprintf(solids_name, MAX_LINE_SIZE, "solids_%d.s", ptr1->region_id);
2572  if (mk_comb(fpout, solids_name, &solids.l, 0, NULL, NULL, NULL, 0, 0, 0, 0, 0, 1, 1))
2573  bu_log("Failed to make combination of solids (%s)!\n\tRegion %s is in ERROR!\n",
2574  solids_name, ptr1->name);
2575 
2576  /* hole components do not get made into regions */
2577  if (is_a_hole(ptr1->region_id)) {
2578  /* just add it to the "holes" group */
2579  if (mk_addmember(solids_name, &holes.l, NULL, WMOP_UNION) == (struct wmember *)NULL)
2580  bu_log("make_regions: mk_addmember failed to add %s to holes group\n", ptr1->name);
2581  goto cont1;
2582  }
2583 
2584  hptr = hole_root;
2585  while (hptr && hptr->group * 1000 + hptr->component != ptr1->region_id)
2586  hptr = hptr->next;
2587 
2588  lptr = NULL;
2589  if (hptr != NULL) {
2590  lptr = hptr->holes;
2591  }
2592 
2593  splt = compsplt_root;
2594  while (splt && splt->ident_to_split != ptr1->region_id)
2595  splt = splt->next;
2596 
2597  mode = ptr1->mode;
2598  if (debug)
2599  bu_log("Build region for %s %d, mode = %d\n", ptr1->name, ptr1->region_id, mode);
2600 
2601  if (splt) {
2602  vect_t norm;
2603  int found;
2604 
2605  /* make a halfspace */
2606  VSET(norm, 0.0, 0.0, 1.0);
2607  snprintf(splt_name, MAX_LINE_SIZE, "splt_%d.s", ptr1->region_id);
2608  mk_half(fpout, splt_name, norm, splt->z);
2609 
2610  /* intersect halfspace with current region */
2611  BU_LIST_INIT(&region.l);
2612  if (mk_addmember(solids_name, &region.l, NULL, WMOP_UNION) == (struct wmember *)NULL)
2613  bu_log("make_regions: mk_addmember failed to add %s to %s\n", solids_name, ptr1->name);
2614 
2615  if (mk_addmember(splt_name, &region.l, NULL, WMOP_INTERSECT) == (struct wmember *)NULL)
2616  bu_log("make_regions: mk_addmember failed to add %s to %s\n", splt_name, ptr1->name);
2617 
2618  while (lptr) {
2619  snprintf(hole_name, MAX_LINE_SIZE, "solids_%d.s", (lptr->group * 1000 + lptr->component));
2620  if (mk_addmember(hole_name, &region.l, NULL, WMOP_SUBTRACT) == (struct wmember *)NULL)
2621  bu_log("make_regions: mk_addmember failed to add %s to %s\n", hole_name, ptr1->name);
2622  lptr = lptr->next;
2623  }
2624  MK_REGION(fpout, &region, ptr1->name, ptr1->region_id, get_fast4_color(ptr1->region_id));
2625 
2626  /* create new region by subtracting halfspace */
2627  BU_LIST_INIT(&region.l);
2628  lptr = NULL;
2629  if (hptr != NULL) {
2630  lptr = hptr->holes;
2631  }
2632 
2633  if (mk_addmember(solids_name, &region.l, NULL, WMOP_UNION) == (struct wmember *)NULL)
2634  bu_log("make_regions: mk_addmember failed to add %s to %s\n", solids_name, ptr1->name);
2635 
2636  if (mk_addmember(splt_name, &region.l, NULL, WMOP_SUBTRACT) == (struct wmember *)NULL)
2637  bu_log("make_regions: mk_addmember failed to add %s to %s\n", splt_name, ptr1->name);
2638 
2639  while (lptr) {
2640  snprintf(hole_name, MAX_LINE_SIZE, "solids_%d.s", (lptr->group * 1000 + lptr->component));
2641  if (mk_addmember(hole_name, &region.l, NULL, WMOP_SUBTRACT) == (struct wmember *)NULL)
2642  bu_log("make_regions: mk_addmember failed to add %s to %s\n", hole_name, ptr1->name);
2643  lptr = lptr->next;
2644  }
2645  ptr2 = Search_ident(name_root, splt->new_ident, &found);
2646  if (found) {
2647  MK_REGION(fpout, &region, ptr2->name, splt->new_ident, get_fast4_color(splt->new_ident));
2648  } else {
2649  sprintf(reg_name, "comp_%d.r", splt->new_ident);
2650  MK_REGION(fpout, &region, reg_name, splt->new_ident, get_fast4_color(splt->new_ident));
2651  }
2652  } else {
2653  BU_LIST_INIT(&region.l);
2654  if (mk_addmember(solids_name, &region.l, NULL, WMOP_UNION) == (struct wmember *)NULL)
2655  bu_log("make_regions: mk_addmember failed to add %s to %s\n", solids_name, ptr1->name);
2656 
2657  while (lptr) {
2658  snprintf(hole_name, MAX_LINE_SIZE, "solids_%d.s", (lptr->group * 1000 + lptr->component));
2659  if (mk_addmember(hole_name, &region.l, NULL, WMOP_SUBTRACT) == (struct wmember *)NULL)
2660  bu_log("make_regions: mk_addmember failed to add %s to %s\n", hole_name, ptr1->name);
2661  lptr = lptr->next;
2662  }
2663  MK_REGION(fpout, &region, ptr1->name, ptr1->region_id, get_fast4_color(ptr1->region_id));
2664  }
2665  cont1:
2666  ptr1 = ptr1->rright;
2667  }
2668 
2669  if (BU_LIST_NON_EMPTY(&holes.l)) {
2670  /* build a "holes" group */
2671  if (mk_comb(fpout, "holes", &holes.l, 0, NULL, NULL, NULL, 0, 0, 0, 0, 0, 1, 1))
2672  bu_log("Failed to make holes group!\n");
2673  }
2674 }
2675 
2676 
2677 #define COLOR_LINE_LEN 256
2678 
2679 static void
2680 read_fast4_colors(char *color_file)
2681 {
2682  FILE *fp;
2683  char colorline[COLOR_LINE_LEN] = {0};
2684  int low, high;
2685  int r, g, b;
2686  struct fast4_color *color;
2687 
2688  if ((fp = fopen(color_file, "rb")) == (FILE *)NULL) {
2689  bu_log("Cannot open color file (%s)\n", color_file);
2690  return;
2691  }
2692 
2693  while (bu_fgets(colorline, COLOR_LINE_LEN, fp) != NULL) {
2694  if (sscanf(colorline, "%d %d %d %d %d", &low, &high, &r, &g, &b) != 5)
2695  continue;
2696 
2697  /* skip invalid colors */
2698  if (r < 0 || 255 < r ||
2699  g < 0 || 255 < g ||
2700  b < 0 || 255 < b)
2701  continue;
2702 
2703  /* skip bad region id ranges */
2704  if (high < low)
2705  continue;
2706 
2707  BU_ALLOC(color, struct fast4_color);
2708  color->low = low;
2709  color->high = high;
2710  color->rgb[0] = r;
2711  color->rgb[1] = g;
2712  color->rgb[2] = b;
2713  BU_LIST_APPEND(&HeadColor.l, &color->l);
2714  }
2715  fclose(fp);
2716 }
2717 
2718 
2719 int
2720 gcv_fastgen4_read(const char *path, struct rt_wdb *wdbp, const struct gcv_opts *UNUSED(options))
2721 {
2722  char *plot_file = NULL;
2723  char *color_file = NULL;
2724 
2725  if (bu_debug & BU_DEBUG_MEM_CHECK)
2726  bu_log("doing memory checking\n");
2727 
2728  if ((fpin=fopen(path, "rb")) == (FILE *)NULL) {
2729  perror("fast4-g");
2730  bu_log("Cannot open FASTGEN4 file (%s)\n", path);
2731  return 0;
2732  }
2733 
2734  fpout = wdbp;
2735 
2736  if (plot_file) {
2737  if ((fp_plot=fopen(plot_file, "wb")) == NULL) {
2738  bu_log("Cannot open plot file (%s)\n", plot_file);
2739  return 0;
2740  }
2741  }
2742 
2743  if (bu_debug) {
2744  bu_printb("librtbu_debug", bu_debug, DEBUG_FORMAT);
2745  bu_log("\n");
2746  }
2747  if (RTG.NMG_debug) {
2748  bu_printb("librt RTG.NMG_debug", RTG.NMG_debug, NMG_DEBUG_FORMAT);
2749  bu_log("\n");
2750  }
2751 
2752  BU_LIST_INIT(&HeadColor.l);
2753  if (color_file)
2754  read_fast4_colors(color_file);
2755 
2756  grid_size = GRID_BLOCK;
2757  grid_points = (point_t *)bu_malloc(grid_size * sizeof(point_t), "fast4-g: grid_points");
2758 
2759  cline_root = (struct cline *)NULL;
2760 
2761  name_root = (struct name_tree *)NULL;
2762 
2763  hole_root = (struct holes *)NULL;
2764 
2765  compsplt_root = (struct compsplt *)NULL;
2766 
2767  min_radius = 2.0 * sqrt(SQRT_SMALL_FASTF);
2768 
2769  name_count = 0;
2770 
2771  vehicle[0] = '\0';
2772 
2773  bu_ptbl_init(&stack, 64, " &stack ");
2774  bu_ptbl_init(&stack2, 64, " &stack2 ");
2775 
2776  BU_LIST_INIT(&hole_head.l);
2777 
2778  if (!quiet)
2779  bu_log("Scanning for HOLE, WALL, and COMPSPLT cards...\n");
2780 
2781  Process_hole_wall();
2782 
2783  rewind(fpin);
2784 
2785  if (!quiet)
2786  bu_log("Building component names....\n");
2787 
2788  Process_input(0);
2789 
2790  rewind(fpin);
2791 
2792  /* Make an ID record if no vehicle card was found */
2793  if (!vehicle[0])
2794  mk_id_units(fpout, path, "in");
2795 
2796  if (!quiet)
2797  bu_log("Building components....\n");
2798 
2799  while (Process_input(1));
2800 
2801  if (!quiet)
2802  bu_log("Building regions and groups....\n");
2803 
2804  /* make regions */
2805  make_regions();
2806 
2807  /* make groups */
2808  f4_do_groups();
2809 
2810  if (debug)
2811  List_holes();
2812 
2813  if (!quiet)
2814  bu_log("%d components converted\n", comp_count);
2815 
2816  bu_free(group_head, "group_head");
2817 
2818  return 1;
2819 }
2820 
2821 
2822 static const struct gcv_converter converters[] = {
2823  {"fastgen4", gcv_fastgen4_read, NULL},
2824  {NULL, NULL, NULL}
2825 };
2826 
2828 
2829 
2830 /*
2831  * Local Variables:
2832  * mode: C
2833  * tab-width: 8
2834  * indent-tabs-mode: t
2835  * c-file-style: "stroustrup"
2836  * End:
2837  * ex: shiftwidth=4 tabstop=8
2838  */
ptrdiff_t ssize_t
Definition: common.h:119
int mk_bot(struct rt_wdb *fp, const char *name, unsigned char mode, unsigned char orientation, unsigned char error_mode, size_t num_vertices, size_t num_faces, fastf_t *vertices, int *faces, fastf_t *thickness, struct bu_bitv *face_mode)
Definition: bot.c:121
#define BU_LIST_FOR(p, structure, hp)
Definition: list.h:365
#define POS_CENTER
Definition: fastgen4_read.c:99
int in_comp_group
#define END_OPEN
void bu_log(const char *,...) _BU_ATTR_PRINTF12
Definition: log.c:176
#define BU_LIST_INSERT(old, new)
Definition: list.h:183
struct cline * next
#define PUSH(ptr)
Definition: fastgen4_read.c:67
Definition: list.h:118
off_t bu_ftell(FILE *stream)
Definition: file.c:344
struct bu_bitv * bu_bitv_new(size_t nbits)
Definition: bitv.c:91
#define COLOR_LINE_LEN
#define BU_DEBUG_MEM_CHECK
Definition: debug.h:54
#define RT_BOT_INTERNAL_MAGIC
Definition: magic.h:85
void make_bot_object(const char *name, struct rt_wdb *wdbp)
void bu_prmem(const char *str)
Definition: malloc.c:516
void pdv_3move(register FILE *plotfp, const fastf_t *pt)
Definition: plot3.c:618
#define CCONE2
#define DEBUG_FORMAT
Definition: raytrace.h:125
Definition: clone.c:90
void bu_ptbl_init(struct bu_ptbl *b, size_t len, const char *str)
Definition: ptbl.c:32
#define VSET(a, b, c, d)
Definition: color.c:53
void bu_vls_trunc(struct bu_vls *vp, int len)
Definition: vls.c:198
#define BU_LIST_IS_EMPTY(hp)
Definition: list.h:295
int bu_fseek(FILE *stream, off_t offset, int origin)
Definition: file.c:330
#define POP2(structure, ptr)
Definition: fastgen4_read.c:77
Definition: wdb.h:64
Header file for the BRL-CAD common definitions.
struct name_tree * nright
#define WMOP_SUBTRACT
Definition: wdb.h:886
struct name_tree * rleft
Definition: gcv.c:8
#define BU_LIST_APPEND(old, new)
Definition: list.h:197
#define WMOP_UNION
Definition: wdb.h:887
struct name_tree * nleft
#define BU_LIST_NON_EMPTY(hp)
Definition: list.h:296
void bu_ptbl_reset(struct bu_ptbl *b)
Definition: ptbl.c:49
#define CHEX2
struct compsplt * next
int made
struct bu_list l
Definition: wdb.h:65
#define BU_BITSET(_bv, bit)
Definition: bitv.h:183
void * bu_malloc(size_t siz, const char *str)
Definition: malloc.c:314
struct hole_list * holes
int component
Definition: ptbl.h:62
#define CLINE
#define REGION_LIST_BLOCK
#define SEEK_SET
Definition: db_open.c:52
int rt_bot_vertex_fuse(struct rt_bot_internal *bot, const struct bn_tol *tol)
Definition: bot.c:3060
void bu_vls_free(struct bu_vls *vp)
Definition: vls.c:248
int ident_to_split
int bu_strncmp(const char *string1, const char *string2, size_t n)
Definition: str.c:191
Definition: color.c:49
fastf_t thick
struct holes * next
void * memset(void *s, int c, size_t n)
int mk_arb8(struct rt_wdb *fp, const char *name, const fastf_t *pts8)
Definition: wdb.c:233
#define RT_G_DEBUG
Definition: raytrace.h:1718
void bu_exit(int status, const char *fmt,...) _BU_ATTR_NORETURN _BU_ATTR_PRINTF23
Definition: bomb.c:195
#define WMOP_INTERSECT
Definition: wdb.h:885
uint32_t NMG_debug
debug bits for NMG's see nmg.h
Definition: raytrace.h:1699
#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
char * bu_vls_strgrab(struct bu_vls *vp)
Definition: vls.c:290
#define bu_strlcpy(dst, src, size)
Definition: str.h:60
#define VOLUME_MODE
Definition: fastgen4_read.c:97
#define BOT
static void top()
#define SQRT_SMALL_FASTF
Definition: defines.h:346
char * options
Definition: gqa.c:56
#define MK_REGION(fp, headp, name, r_id, rgb)
Definition: fastgen4_read.c:51
#define DEBUG_MEM_FULL
18 –>> BU_DEBUG_MEM_CHECK
Definition: raytrace.h:103
int mk_half(struct rt_wdb *fp, const char *name, const vect_t norm, fastf_t d)
int type
size_t bu_vls_strlen(const struct bu_vls *vp)
Definition: vls.c:189
void pdv_3cont(register FILE *plotfp, const fastf_t *pt)
Definition: plot3.c:630
struct name_tree * name_root
void * bu_realloc(void *ptr, size_t siz, const char *str)
int gcv_fastgen4_read(const char *path, struct rt_wdb *wdbp, const struct gcv_opts *options)
#define HOLE
void bu_printb(const char *s, unsigned long v, const char *bits)
#define UNUSED(parameter)
Definition: common.h:239
struct wmember * mk_addmember(const char *name, struct bu_list *headp, mat_t mat, int op)
Definition: reg.c:181
goto out
Definition: nmg_mod.c:3846
#define POP(structure, ptr)
Definition: fastgen4_read.c:68
#define CSPHERE
char * bu_vls_addr(const struct bu_vls *vp)
Definition: vls.c:111
#define WALL
int bu_mem_barriercheck(void)
Definition: malloc.c:660
int element_id
int mk_comb(struct rt_wdb *wdbp, const char *combname, struct bu_list *headp, int region_kind, const char *shadername, const char *shaderargs, const unsigned char *rgb, int id, int air, int material, int los, int inherit, int append_ok, int gift_semantics)
Definition: reg.c:230
int bu_vls_gets(struct bu_vls *vp, FILE *fp)
Definition: vls.c:621
int mk_cline(struct rt_wdb *fp, const char *name, const point_t V, const vect_t height, fastf_t radius, fastf_t thickness)
Definition: cline.c:40
int rt_bot_face_fuse(struct rt_bot_internal *bot)
Definition: bot.c:3283
int bu_strcmp(const char *string1, const char *string2)
Definition: str.c:171
struct hole_list * next
int bu_debug
Definition: globals.c:87
#define BU_LIST_INIT(_hp)
Definition: list.h:148
const struct gcv_plugin_info gcv_plugin_conv_fastgen4_read
struct bn_tol wdb_tol
Definition: raytrace.h:1269
struct cline * cline_root
int group
#define CCONE1
int mk_id_units(struct rt_wdb *fp, const char *title, const char *units)
Definition: id.c:50
#define CCONE3
char * name
fastf_t radius
void bu_vls_printf(struct bu_vls *vls, const char *fmt,...) _BU_ATTR_PRINTF23
Definition: vls.c:694
struct holes * hole_root
#define PUSH2(ptr)
Definition: fastgen4_read.c:76
struct bu_list l
#define PLATE_MODE
Definition: fastgen4_read.c:96
void bu_vls_trimspace(struct bu_vls *vp)
Definition: vls.c:678
void bu_free(void *ptr, const char *str)
Definition: malloc.c:328
#define mk_lfcomb(fp, name, headp, region)
Definition: wdb.h:890
#define MAX_LINE_SIZE
fastf_t z
char * bu_fgets(char *s, int size, FILE *stream)
Definition: fgets.c:31
#define BU_VLS_INIT_ZERO
Definition: vls.h:84
#define BU_LIST_DEQUEUE(cur)
Definition: list.h:209
#define CK_TREE_MAGIC(ptr)
Definition: fastgen4_read.c:88
Definition: bitv.h:105
int mk_trc_h(struct rt_wdb *fp, const char *name, const point_t base, const vect_t height, fastf_t radbase, fastf_t radtop)
Definition: vls.h:56
unsigned char rgb[3]
double fastf_t
Definition: defines.h:300
struct bu_list l
magic # and doubly linked list
Definition: raytrace.h:538
int mk_sph(struct rt_wdb *fp, const char *name, const point_t center, fastf_t radius)
struct compsplt * compsplt_root
struct bu_list l
Definition: raytrace.h:1264
#define GRID_BLOCK
struct name_tree * rright
#define POS_FRONT
#define BU_LIST_FIRST(structure, hp)
Definition: list.h:312
#define bu_strdup(s)
Definition: str.h:71
#define NAME_TREE_MAGIC
Definition: fastgen4_read.c:87
uint32_t magic
#define BU_STR_EQUAL(s1, s2)
Definition: str.h:126
struct rt_g RTG
Definition: globals.c:39