BRL-CAD
bigE.c
Go to the documentation of this file.
1 /* B I G E . C
2  * BRL-CAD
3  *
4  * Copyright (c) 1997-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 libged */
21 /** @{ */
22 /** @file libged/bigE.c
23  *
24  * This module implements the 'E' command.
25  *
26  */
27 /** @} */
28 
29 #include "common.h"
30 
31 #include <stdlib.h>
32 #include <string.h>
33 #include <time.h>
34 
35 #include "bu/debug.h"
36 #include "bu/getopt.h"
37 #include "vmath.h"
38 #include "nmg.h"
39 #include "rtgeom.h"
40 #include "rtfunc.h"
41 
42 #include "./ged_private.h"
43 
44 
45 /* #define debug 1 */
46 
47 union E_tree *build_etree(union tree *tp, struct _ged_client_data *dgcdp);
48 
49 /* segment types (stored in the "seg_stp" field of the (struct seg) */
50 #define ON_SURF (struct soltab *)0x1
51 #define IN_SOL (struct soltab *)0x2
52 #define ON_INT (struct soltab *)0x3
53 
54 #define NOT_SEG_OVERLAP(_a, _b) ((_a->seg_out.hit_dist <= _b->seg_in.hit_dist) || (_b->seg_out.hit_dist <= _a->seg_in.hit_dist))
55 
56 /* RT_FREE_SEG_LIST assumed list head is a "struct seg" */
57 #define MY_FREE_SEG_LIST(_segheadp, _res) { \
58  struct seg *_a; \
59  while (BU_LIST_WHILE (_a, seg, (_segheadp))) { \
60  BU_LIST_DEQUEUE(&(_a->l)); \
61  RT_FREE_SEG(_a, _res); \
62  } }
63 
64 /* stolen from g_half.c */
65 struct half_specific {
66  plane_t half_eqn; /* Plane equation, outward normal */
67  vect_t half_Xbase; /* "X" basis direction */
68  vect_t half_Ybase; /* "Y" basis direction */
69 };
70 #define HALF_NULL ((struct half_specific *)0)
71 
72 /* structures for building a tree corresponding to the region to be
73  * drawn uses the same "op" values as "union tree"
74  */
75 union E_tree {
76  uint32_t magic;
77 
78  struct E_node {
79  /* the operator nodes */
80  uint32_t magic;
81  int op;
82  union E_tree *left;
83  union E_tree *right;
84  } n;
85 
86  struct E_leaf {
87  /* the leaf nodes */
88  uint32_t magic;
89  int op;
90  struct model *m; /* NMG version of this leaf solid */
91  struct bu_list seghead; /* head of list of segments for this leaf solid */
92  struct bu_ptbl edge_list; /* list of edges from above NMG */
93  struct soltab *stp; /* the usual soltab pointer */
94  unsigned char do_not_free_model; /* A flag indicating that the
95  * NMG model pointer is a
96  * reference to the NMG model
97  * in the soltab structure.
98  */
99  } l;
100 };
101 
102 
103 #define E_TREE_MAGIC 0x45545245
104 #define CK_ETREE(_p) BU_CKMAG(_p, E_TREE_MAGIC, "struct E_tree")
105 
106 
107 HIDDEN union E_tree *
108 add_solid(const struct directory *dp,
109  matp_t mat,
110  struct _ged_client_data *dgcdp)
111 {
112  union E_tree *eptr = NULL;
113  struct nmgregion *r = NULL;
114  struct rt_db_internal intern;
115  int id;
116  int solid_is_plate_mode_bot=0;
117 
118  BU_ALLOC(eptr, union E_tree);
119  eptr->magic = E_TREE_MAGIC;
120 
121  id = rt_db_get_internal(&intern, dp, dgcdp->gedp->ged_wdbp->dbip, mat, &rt_uniresource);
122  if (id < 0) {
123  bu_vls_printf(dgcdp->gedp->ged_result_str, "Failed to get internal form of %s\n", dp->d_namep);
124  eptr->l.m = (struct model *)NULL;
125  return eptr;
126  }
127  if (id == ID_COMBINATION) {
128  /* do explicit expansion of referenced combinations */
129 
130  struct rt_comb_internal *comb;
131 
132  bu_free((char *)eptr, "eptr");
133 
134  comb = (struct rt_comb_internal *)intern.idb_ptr;
135  RT_CK_COMB(comb);
136 
137  eptr = build_etree(comb->tree, dgcdp);
138  rt_db_free_internal(&intern);
139  return eptr;
140  }
141  if (id == ID_HALF) {
142  eptr->l.m = NULL;
143  dgcdp->num_halfs++;
144  } else if (id == ID_NMG) {
145  /* steal the nmg model */
146  eptr->l.m = (struct model *)intern.idb_ptr;
147  eptr->l.do_not_free_model = 1;
148  } else {
149  /* create the NMG version of this solid */
150  eptr->l.m = nmg_mm();
151 
152  if (!OBJ[id].ft_tessellate ||
153  OBJ[id].ft_tessellate(&r, eptr->l.m, &intern,
154  &dgcdp->gedp->ged_wdbp->wdb_ttol,
155  &dgcdp->gedp->ged_wdbp->wdb_tol) < 0)
156  {
157  nmg_km(eptr->l.m);
158  eptr->l.m = NULL;
159  }
160  }
161 
162  /* get the soltab stuff */
163  BU_ALLOC(eptr->l.stp, struct soltab);
164  eptr->l.stp->l.magic = RT_SOLTAB_MAGIC;
165  eptr->l.stp->l2.magic = RT_SOLTAB2_MAGIC;
166  eptr->l.stp->st_dp = dp;
167  eptr->l.stp->st_matp = mat;
168 
169  {
170  struct rt_bot_internal *bot;
171  struct rt_db_internal intern2;
172 
173  if (dgcdp->do_polysolids) {
174  struct shell *s=(struct shell *)NULL;
175 
176  /* create and prep a BoT version of this solid */
177  if (eptr->l.m) {
178  r = BU_LIST_FIRST(nmgregion, &eptr->l.m->r_hd);
179  s = BU_LIST_FIRST(shell, &r->s_hd);
180  }
181 
182  if (solid_is_plate_mode_bot
183  || !eptr->l.m
184  || (bot=nmg_bot(s, &dgcdp->gedp->ged_wdbp->wdb_tol)) == (struct rt_bot_internal *)NULL)
185  {
186  eptr->l.stp->st_id = id;
187  eptr->l.stp->st_meth = &OBJ[id];
188  if (rt_obj_prep(eptr->l.stp, &intern, dgcdp->rtip) < 0) {
189  bu_vls_printf(dgcdp->gedp->ged_result_str, "Prep failure for solid '%s'\n", dp->d_namep);
190  }
191  } else {
192  RT_DB_INTERNAL_INIT(&intern2);
193  intern2.idb_major_type = DB5_MAJORTYPE_BRLCAD;
194  intern2.idb_type = ID_BOT;
195  intern2.idb_meth = &OBJ[ID_BOT];
196  intern2.idb_ptr = (void *)bot;
197  eptr->l.stp->st_id = ID_BOT;
198  eptr->l.stp->st_meth = &OBJ[ID_BOT];
199  if (rt_obj_prep(eptr->l.stp, &intern2, dgcdp->rtip) < 0) {
200  bu_vls_printf(dgcdp->gedp->ged_result_str, "Prep failure for solid '%s'\n", dp->d_namep);
201  }
202 
203  rt_db_free_internal(&intern2);
204  }
205  } else {
206  /* prep this solid */
207 
208  eptr->l.stp->st_id = id;
209  eptr->l.stp->st_meth = &OBJ[id];
210  if (rt_obj_prep(eptr->l.stp, &intern, dgcdp->rtip) < 0)
211  bu_vls_printf(dgcdp->gedp->ged_result_str, "Prep failure for solid '%s'\n", dp->d_namep);
212  }
213  }
214 
215  if (id != ID_NMG)
216  rt_db_free_internal(&intern);
217 
218  /* add this leaf to the leaf list */
219  bu_ptbl_ins(&dgcdp->leaf_list, (long *)eptr);
220 
221  return eptr;
222 }
223 
224 
225 /* build an E_tree corresponding to the region tree (tp) */
226 union E_tree *
227 build_etree(union tree *tp,
228  struct _ged_client_data *dgcdp)
229 {
230  union E_tree *eptr = NULL;
231  struct soltab *stp;
232  struct directory *dp;
233 
234  RT_CK_TREE(tp);
235 
236  switch (tp->tr_op) {
237  case OP_UNION:
238  case OP_SUBTRACT:
239  case OP_INTERSECT:
240  BU_ALLOC(eptr, union E_tree);
241  eptr->magic = E_TREE_MAGIC;
242  eptr->n.op = tp->tr_op;
243  eptr->n.left = build_etree(tp->tr_b.tb_left, dgcdp);
244  eptr->n.right = build_etree(tp->tr_b.tb_right, dgcdp);
245  break;
246  case OP_SOLID:
247  stp = tp->tr_a.tu_stp;
248  eptr = add_solid(stp->st_dp, stp->st_matp, dgcdp);
249  eptr->l.op = tp->tr_op;
250  BU_LIST_INIT(&eptr->l.seghead);
251  break;
252  case OP_DB_LEAF:
253  if ((dp=db_lookup(dgcdp->gedp->ged_wdbp->dbip, tp->tr_l.tl_name, LOOKUP_NOISY)) == RT_DIR_NULL) {
254  break;
255  }
256  eptr = add_solid(dp, tp->tr_l.tl_mat, dgcdp);
257  eptr->l.op = tp->tr_op;
258  BU_LIST_INIT(&eptr->l.seghead);
259  break;
260  case OP_NOP:
261  /* add a NULL solid */
262  BU_ALLOC(eptr, union E_tree);
263  eptr->magic = E_TREE_MAGIC;
264  eptr->l.m = (struct model *)NULL;
265  break;
266  default:
267  bu_bomb("build_etree() Unknown tr_op\n");
268  }
269  return eptr;
270 }
271 
272 
273 /* a handy routine (for debugging) that prints asegment list */
274 void
275 show_seg(struct bu_list *seg, int str)
276 {
277  struct seg *ptr;
278 
279  if (!seg)
280  bu_log("%d - NULL seg list\n", str);
281  else {
282  if (BU_LIST_IS_EMPTY(seg))
283  bu_log("%d - empty\n", str);
284  else {
285  bu_log("%d:\n", str);
286  for (BU_LIST_FOR (ptr, seg, seg)) {
287  if (ptr->seg_stp == ON_SURF)
288  bu_log("\t %g to %g (ON_SURF)\n", ptr->seg_in.hit_dist, ptr->seg_out.hit_dist);
289  else if (ptr->seg_stp == ON_INT)
290  bu_log("\t %g to %g (ON_INT)\n", ptr->seg_in.hit_dist, ptr->seg_out.hit_dist);
291  else if (ptr->seg_stp == IN_SOL)
292  bu_log("\t %g to %g (IN)\n", ptr->seg_in.hit_dist, ptr->seg_out.hit_dist);
293  else
294  bu_log("\t %g to %g (?)\n", ptr->seg_in.hit_dist, ptr->seg_out.hit_dist);
295  bu_log("\t\t(%g %g %g) <-> (%g %g %g)\n", V3ARGS(ptr->seg_in.hit_point),
296  V3ARGS(ptr->seg_out.hit_point));
297  }
298  }
299  }
300 }
301 
302 
303 /* given a segment list, eliminate any overlaps in the segments */
304 HIDDEN void
305 eliminate_overlaps(struct bu_list *seghead,
306  struct _ged_client_data *dgcdp)
307 {
308  struct seg *a, *b, *nextb;
309 
310  a = BU_LIST_FIRST(seg, seghead);
311  while (BU_LIST_NOT_HEAD(&a->l, seghead)) {
312  b = BU_LIST_PNEXT(seg, &a->l);
313  if (BU_LIST_IS_HEAD(&b->l, seghead))
314  break;
315 
316  while (BU_LIST_NOT_HEAD(&b->l, seghead)) {
317  nextb = BU_LIST_PNEXT(seg, &b->l);
318  if (NOT_SEG_OVERLAP(a, b))
319  break;
320 
321  if (b->seg_in.hit_dist < a->seg_out.hit_dist) {
322  if (b->seg_out.hit_dist > a->seg_out.hit_dist)
324 
325  BU_LIST_DEQUEUE(&b->l);
326  RT_FREE_SEG(b, dgcdp->ap->a_resource);
327  b = nextb;
328  continue;
329  }
330 
331  b = nextb;
332  }
333 
334  a = BU_LIST_PNEXT(seg, &a->l);
335  }
336 }
337 
338 
339 /* perform the intersection of two segments the result is assigned the
340  * provided type
341  */
342 HIDDEN void
344  struct seg *B,
345  struct bu_list *seghead,
346  struct soltab *type,
347  struct _ged_client_data *dgcdp)
348 {
349  struct seg *tmp=(struct seg *)NULL;
350 
351  if (NOT_SEG_OVERLAP(A, B))
352  return;
353 
354  RT_GET_SEG(tmp, dgcdp->ap->a_resource);
355  if (A->seg_in.hit_dist <= B->seg_in.hit_dist) {
356  if (B->seg_out.hit_dist <= A->seg_out.hit_dist) {
357  *tmp = *B;
358  tmp->seg_stp = type;
359  } else {
360  tmp->seg_in.hit_dist = B->seg_in.hit_dist;
361  tmp->seg_out.hit_dist = A->seg_out.hit_dist;
362  tmp->seg_stp = type;
363  }
364  } else {
365  if (B->seg_out.hit_dist >= A->seg_out.hit_dist) {
366  *tmp = *A;
367  tmp->seg_stp = type;
368  } else {
369  tmp->seg_in.hit_dist = A->seg_in.hit_dist;
370  tmp->seg_out.hit_dist = B->seg_out.hit_dist;
371  tmp->seg_stp = type;
372  }
373  }
374  if (tmp) {
375  BU_LIST_INSERT(seghead, &tmp->l);
376  }
377 
378  return;
379 }
380 
381 
382 /* perform the subtraction of one segment from another the result is
383  * assigned the type from segment A
384  */
385 HIDDEN void
386 do_subtract(struct seg *A,
387  struct seg *B,
388  struct bu_list *seghead,
389  struct _ged_client_data *dgcdp)
390 {
391  struct seg *tmp=(struct seg *)NULL;
392 
393 
394  if (NOT_SEG_OVERLAP(A, B)) {
395  RT_GET_SEG(tmp, dgcdp->ap->a_resource);
396  *tmp = *A;
397  BU_LIST_INSERT(seghead, &tmp->l);
398  return;
399  }
400 
401  if (B->seg_in.hit_dist<= A->seg_in.hit_dist) {
402  if (B->seg_out.hit_dist < A->seg_out.hit_dist) {
403  RT_GET_SEG(tmp, dgcdp->ap->a_resource);
404  *tmp = *A;
405  tmp->seg_in.hit_dist = B->seg_out.hit_dist;
406  BU_LIST_INSERT(seghead, &tmp->l);
407  return;
408  } else {
409  return;
410  }
411  } else {
412  if (B->seg_out.hit_dist >= A->seg_out.hit_dist) {
413  RT_GET_SEG(tmp, dgcdp->ap->a_resource);
414  *tmp = *A;
415  tmp->seg_out.hit_dist = B->seg_in.hit_dist;
416  BU_LIST_INSERT(seghead, &tmp->l);
417  return;
418  } else {
419  RT_GET_SEG(tmp, dgcdp->ap->a_resource);
420  tmp->seg_in.hit_dist = A->seg_in.hit_dist;
421  tmp->seg_out.hit_dist = B->seg_in.hit_dist;
422  tmp->seg_stp = A->seg_stp;
423  BU_LIST_INSERT(seghead, &tmp->l);
424  RT_GET_SEG(tmp, dgcdp->ap->a_resource);
425  tmp->seg_in.hit_dist = B->seg_out.hit_dist;
426  tmp->seg_out.hit_dist = A->seg_out.hit_dist;
427  tmp->seg_stp = A->seg_stp;
428  BU_LIST_INSERT(seghead, &tmp->l);
429  return;
430  }
431  }
432 }
433 
434 
435 HIDDEN void
436 promote_ints(struct bu_list *head,
437  struct _ged_client_data *dgcdp)
438 {
439  struct seg *a, *b, *tmp;
440 
441 #ifdef debug
442  bu_log("In promote_ints():\n");
443  show_seg(head, "SEGS");
444  for (BU_LIST_FOR (a, seg, head)) {
445  b = BU_LIST_PNEXT(seg, &a->l);
446  if (BU_LIST_IS_HEAD(&b->l, head))
447  break;
448 
449  if (b->seg_in.hit_dist < a->seg_in.hit_dist)
450  bu_log("\tsegments out of order:\n");
451  }
452 #endif
453 
454  a = BU_LIST_FIRST(seg, head);
455  while (BU_LIST_NOT_HEAD(&a->l, head)) {
456  b = BU_LIST_PNEXT(seg, &a->l);
457  while (BU_LIST_NOT_HEAD(&b->l, head)) {
458  if (a->seg_stp == ON_INT && b->seg_stp == ON_SURF) {
459  if (NOT_SEG_OVERLAP(a, b)) {
460  b = BU_LIST_PNEXT(seg, &b->l);
461  continue;
462  }
463 
464  if (ZERO(a->seg_in.hit_dist - b->seg_in.hit_dist)
465  && ZERO(a->seg_out.hit_dist - b->seg_out.hit_dist))
466  {
467  a->seg_stp = ON_SURF;
468  tmp = b;
469  b = BU_LIST_PNEXT(seg, &b->l);
470  BU_LIST_DEQUEUE(&tmp->l);
471  RT_FREE_SEG(tmp, dgcdp->ap->a_resource);
472  continue;
473  }
474 
475  if (ZERO(a->seg_out.hit_dist - b->seg_out.hit_dist))
477  else if (a->seg_out.hit_dist < b->seg_out.hit_dist) {
478  if (b->seg_in.hit_dist > a->seg_in.hit_dist)
480  else {
481  tmp = a;
482  a = BU_LIST_PLAST(seg, &a->l);
483  BU_LIST_DEQUEUE(&tmp->l);
484  RT_FREE_SEG(tmp, dgcdp->ap->a_resource);
485  break;
486  }
487  } else if (ZERO(a->seg_in.hit_dist - b->seg_in.hit_dist)) {
488  fastf_t tmp_dist;
489 
490  tmp_dist = a->seg_out.hit_dist;
493  b->seg_out.hit_dist = tmp_dist;
494  a->seg_stp = ON_SURF;
495  b->seg_stp = ON_INT;
496  } else {
497  RT_GET_SEG(tmp, dgcdp->ap->a_resource);
498  *tmp = *a;
499  tmp->seg_in.hit_dist = b->seg_out.hit_dist;
501  BU_LIST_APPEND(&b->l, &tmp->l);
502  }
503  } else if (b->seg_stp == ON_INT && a->seg_stp == ON_SURF) {
504  if (NOT_SEG_OVERLAP(b, a)) {
505  b = BU_LIST_PNEXT(seg, &b->l);
506  continue;
507  }
508 
509  if (ZERO(b->seg_in.hit_dist - a->seg_in.hit_dist)
510  && ZERO(b->seg_out.hit_dist - a->seg_out.hit_dist))
511  {
512  b->seg_stp = ON_SURF;
513  tmp = a;
514  a = BU_LIST_PLAST(seg, &a->l);
515  BU_LIST_DEQUEUE(&tmp->l);
516  RT_FREE_SEG(tmp, dgcdp->ap->a_resource);
517  break;
518  }
519 
520  if (ZERO(b->seg_out.hit_dist - a->seg_out.hit_dist)) {
521  tmp = b;
522  b = BU_LIST_PNEXT(seg, &b->l);
523  BU_LIST_DEQUEUE(&tmp->l);
524  RT_FREE_SEG(tmp, dgcdp->ap->a_resource);
525  } else if (b->seg_out.hit_dist < a->seg_out.hit_dist) {
526  if (a->seg_in.hit_dist > b->seg_in.hit_dist)
528  else {
529  tmp = b;
530  b = BU_LIST_PNEXT(seg, &b->l);
531  BU_LIST_DEQUEUE(&tmp->l);
532  RT_FREE_SEG(tmp, dgcdp->ap->a_resource);
533  continue;
534  }
535  } else if (ZERO(b->seg_in.hit_dist - a->seg_in.hit_dist)) {
537  } else {
538  RT_GET_SEG(tmp, dgcdp->ap->a_resource);
539  *tmp = *b;
540  tmp->seg_in.hit_dist = a->seg_out.hit_dist;
542  BU_LIST_APPEND(&a->l, &tmp->l);
543  }
544  }
545 
546  if ((a->seg_stp != ON_INT) || (b->seg_stp != ON_INT)) {
547  b = BU_LIST_PNEXT(seg, &b->l);
548  continue;
549  }
550 
551  if (NOT_SEG_OVERLAP(a, b)) {
552  b = BU_LIST_PNEXT(seg, &b->l);
553  continue;
554  }
555 
556 #ifdef debug
557  bu_log("\tfound overlapping ON_INT segs:\n");
558 #endif
559 
560  if (ZERO(a->seg_in.hit_dist - b->seg_in.hit_dist)
561  && ZERO(a->seg_out.hit_dist - b->seg_out.hit_dist))
562  {
563 #ifdef debug
564  bu_log("Promoting A, eliminating B\n");
565 #endif
566 
567  a->seg_stp = ON_SURF;
568  BU_LIST_DEQUEUE(&b->l);
569  RT_FREE_SEG(b, dgcdp->ap->a_resource);
570  break;
571  }
572 
573  if (ZERO(a->seg_out.hit_dist - b->seg_out.hit_dist)) {
574  b->seg_stp = ON_SURF;
576 
577 #ifdef debug
578  bu_log("Promoting B, reducing A:\n");
579 #endif
580  } else if (a->seg_out.hit_dist < b->seg_out.hit_dist) {
581  if (b->seg_in.hit_dist > a->seg_in.hit_dist) {
582  RT_GET_SEG(tmp, dgcdp->ap->a_resource);
583  tmp->seg_stp = ON_SURF;
584  tmp->seg_in.hit_dist = b->seg_in.hit_dist;
585  tmp->seg_out.hit_dist = a->seg_out.hit_dist;
587  a->seg_out.hit_dist = tmp->seg_in.hit_dist;
588  BU_LIST_INSERT(&b->l, &tmp->l);
589 
590 #ifdef debug
591  bu_log("--==__ overlap\n");
592 #endif
593  } else {
595  a->seg_stp = ON_SURF;
596 
597 #ifdef debug
598  bu_log("A within B\n");
599 #endif
600  }
601  } else {
602  if (ZERO(a->seg_in.hit_dist - b->seg_in.hit_dist)) {
603  fastf_t tmp_dist;
604 
605  tmp_dist = a->seg_out.hit_dist;
607  a->seg_stp = ON_SURF;
609  b->seg_out.hit_dist = tmp_dist;
610  } else {
611  RT_GET_SEG(tmp, dgcdp->ap->a_resource);
612  *tmp = *a;
613  tmp->seg_in.hit_dist = b->seg_out.hit_dist;
615  b->seg_stp = ON_SURF;
616  BU_LIST_APPEND(&b->l, &tmp->l);
617 
618 #ifdef debug
619  bu_log("B within A:\n");
620 #endif
621  }
622  }
623  b = BU_LIST_PNEXT(seg, &b->l);
624  }
625  a = BU_LIST_PNEXT(seg, &a->l);
626  }
627 
628 #ifdef debug
629  bu_log("Results of promote_ints()\n");
630  show_seg(head, "SEGS");
631 #endif
632 }
633 
634 
635 /* Evaluate an operation on the operands (segment lists) */
636 HIDDEN struct bu_list *
637 eval_op(struct bu_list *A,
638  int op,
639  struct bu_list *B,
640  struct _ged_client_data *dgcdp)
641 {
642  struct seg *sega, *segb, *tmp, *next;
643  struct bu_list ret, ons, ins;
644  int inserted;
645 
646  BU_LIST_INIT(&ret);
647 
648 #ifdef debug
649  bu_log("In eval_op:\n");
650  show_seg(A, "\tA:");
651  show_seg(B, "\tB:");
652 #endif
653 
654  switch (op) {
655  case OP_SUBTRACT:
656 
657 #ifdef debug
658  bu_log("\t\tSUBTACT\n");
659 #endif
660 
661  if (BU_LIST_IS_EMPTY(A)) {
662  MY_FREE_SEG_LIST(B, dgcdp->ap->a_resource);
663  bu_free((char *)B, "bu_list");
664 
665 #ifdef debug
666  show_seg(A, "Returning");
667 #endif
668 
669  return A;
670  } else if (BU_LIST_IS_EMPTY(B)) {
671  bu_free((char *)B, "bu_list");
672 
673 #ifdef debug
674  show_seg(A, "Returning");
675 #endif
676 
677  return A;
678  }
679 
680  /* A - B:
681  * keep segments:
682  * ON_A - IN_B
683  * ON_A - ON_B
684  * ON_B + IN_A
685  * IN_A - IN_B
686  */
687  for (BU_LIST_FOR (sega, seg, A)) {
688  for (BU_LIST_FOR (segb, seg, B)) {
689  if (sega->seg_stp == ON_INT && segb->seg_stp == ON_INT) {
690  do_intersect(sega, segb, &ret, ON_SURF, dgcdp);
691  } else if (sega->seg_stp == ON_SURF || sega->seg_stp == ON_INT) {
692  do_subtract(sega, segb, &ret, dgcdp);
693  } else if (segb->seg_stp == ON_SURF || segb->seg_stp == ON_INT) {
694  do_intersect(segb, sega, &ret, segb->seg_stp, dgcdp);
695  }
696  }
697  }
698  MY_FREE_SEG_LIST(B, dgcdp->ap->a_resource);
699  bu_free((char *)B, "bu_list");
700  MY_FREE_SEG_LIST(A, dgcdp->ap->a_resource);
701  BU_LIST_INSERT_LIST(A, &ret);
702 
703 #ifdef debug
704  show_seg(A, "Returning");
705 #endif
706 
707  return A;
708  case OP_INTERSECT:
709 
710 #ifdef debug
711  bu_log("\t\tINTERSECT\n");
712 #endif
713 
714  if (BU_LIST_IS_EMPTY(A) || BU_LIST_IS_EMPTY(B)) {
715  MY_FREE_SEG_LIST(A, dgcdp->ap->a_resource);
716  MY_FREE_SEG_LIST(B, dgcdp->ap->a_resource);
717  bu_free((char *)B, "bu_list");
718 
719 #ifdef debug
720  show_seg(A, "Returning");
721 #endif
722 
723  return A;
724  }
725  /* A + B
726  *
727  * This is merely the intersection of segments from A with
728  * those from B. The two different calls to
729  * "do_intersect" get the types (IN, ON) right
730  */
731  for (BU_LIST_FOR (sega, seg, A)) {
732  for (BU_LIST_FOR (segb, seg, B)) {
733  if (sega->seg_stp == ON_INT && segb->seg_stp == ON_INT)
734  do_intersect(sega, segb, &ret, ON_SURF, dgcdp);
735  else if (sega->seg_stp == ON_SURF || sega->seg_stp == ON_INT)
736  do_intersect(sega, segb, &ret, sega->seg_stp, dgcdp);
737  else
738  do_intersect(segb, sega, &ret, segb->seg_stp, dgcdp);
739  }
740  }
741  MY_FREE_SEG_LIST(B, dgcdp->ap->a_resource);
742  bu_free((char *)B, "bu_list");
743  MY_FREE_SEG_LIST(A, dgcdp->ap->a_resource);
744  BU_LIST_INSERT_LIST(A, &ret)
745 
746 #ifdef debug
747  show_seg(A, "Returning");
748 #endif
749 
750  return A;
751  case OP_UNION:
752 
753 #ifdef debug
754  bu_log("\t\tUNION\n");
755 #endif
756 
757  if (BU_LIST_IS_EMPTY(A)) {
758  bu_free((char *)A, "bu_list");
759 
760 #ifdef debug
761  show_seg(B, "Returning B (A is empty)");
762 #endif
763 
764  return B;
765  }
766  if (BU_LIST_IS_EMPTY(B)) {
767  bu_free((char *)B, "bu_list");
768 
769 #ifdef debug
770  show_seg(A, "Returning A (B is empty)");
771 #endif
772 
773  return A;
774  }
775  /* A u B:
776  * keep segments:
777  * ON_A - IN_B (ON)
778  * IN_B + ON_A (IN)
779  * ON_B - IN_A (ON)
780  * IN_A + ON_B (IN)
781  * all remaining unique ON or IN segments
782  */
783 
784  /* create two new lists, one with all the ON segments, the
785  * other with all the IN segments
786  */
787  BU_LIST_INIT(&ons);
788  BU_LIST_INIT(&ins);
789 
790  /* Put the A operand segments on the lists */
791  while (BU_LIST_WHILE (sega, seg, A)) {
792  BU_LIST_DEQUEUE(&sega->l);
793 
794  if (sega->seg_stp == ON_SURF || sega->seg_stp == ON_INT) {
795  BU_LIST_INSERT(&ons, &sega->l);
796  } else {
797  BU_LIST_INSERT(&ins, &sega->l);
798  }
799  }
800 
801  /* insert the B operand segments in the lists (maintaining
802  * order from smaller starting hit distance to larger
803  */
804  while (BU_LIST_WHILE (segb, seg, B)) {
805  BU_LIST_DEQUEUE(&segb->l);
806 
807  if (segb->seg_stp == IN_SOL) {
808  inserted = 0;
809  for (BU_LIST_FOR (tmp, seg, &ins)) {
810  if (tmp->seg_in.hit_dist >= segb->seg_in.hit_dist) {
811  inserted = 1;
812  BU_LIST_INSERT(&tmp->l, &segb->l);
813  break;
814  }
815  }
816  if (!inserted)
817  BU_LIST_INSERT(&ins, &segb->l);
818  } else {
819  inserted = 0;
820  for (BU_LIST_FOR (tmp, seg, &ons)) {
821  if (tmp->seg_in.hit_dist >= segb->seg_in.hit_dist) {
822  inserted = 1;
823  BU_LIST_INSERT(&tmp->l, &segb->l);
824  break;
825  }
826  }
827  if (!inserted)
828  BU_LIST_INSERT(&ons, &segb->l);
829  }
830  }
831 
832  /* promote intersecting ON_INT's to ON_SURF */
833  promote_ints(&ons, dgcdp);
834 
835  /* make sure the segments are unique */
836  eliminate_overlaps(&ins, dgcdp);
837  eliminate_overlaps(&ons, dgcdp);
838 
839 #ifdef debug
840  show_seg(&ons, "ONS");
841  show_seg(&ins, "INS");
842 #endif
843 
844  /* subtract INS from ONS */
845 #ifdef debug
846  bu_log("doing subtraction:\n");
847 #endif
848  sega = BU_LIST_FIRST(seg, &ons);
849  while (BU_LIST_NOT_HEAD(&sega->l, &ons)) {
850  next = BU_LIST_PNEXT(seg, &sega->l);
851 
852 #ifdef debug
853  bu_log("A is %g to %g:\n", sega->seg_in.hit_dist, sega->seg_out.hit_dist);
854 #endif
855 
856  for (BU_LIST_FOR (segb, seg, &ins)) {
857 #ifdef debug
858  bu_log("\tcomparing to B %g to %g\n", segb->seg_in.hit_dist, segb->seg_out.hit_dist);
859 #endif
860 
861  if (NOT_SEG_OVERLAP(sega, segb)) {
862 #ifdef debug
863  bu_log("\t\tNo overlap!!\n");
864 #endif
865 
866  continue;
867  }
868 
869  if (segb->seg_in.hit_dist <= sega->seg_in.hit_dist &&
870  segb->seg_out.hit_dist >= sega->seg_out.hit_dist) {
871 #ifdef debug
872  bu_log("\t\teliminating A\n");
873 #endif
874 
875  /* eliminate sega */
876  BU_LIST_DEQUEUE(&sega->l);
877  RT_FREE_SEG(sega, dgcdp->ap->a_resource);
878  sega = next;
879  break;
880  }
881 
882  if (segb->seg_in.hit_dist > sega->seg_in.hit_dist &&
883  segb->seg_out.hit_dist < sega->seg_out.hit_dist)
884  {
885  /* split sega */
886  RT_GET_SEG(tmp, dgcdp->ap->a_resource);
887  *tmp = *sega;
888  tmp->seg_in.hit_dist = segb->seg_out.hit_dist;
889  sega->seg_out.hit_dist = segb->seg_in.hit_dist;
890  BU_LIST_APPEND(&sega->l, &tmp->l);
891  next = tmp;
892 
893 #ifdef debug
894  bu_log("\t\tsplit A into: %g to %g and %g to %g\n", sega->seg_in.hit_dist, sega->seg_out.hit_dist, tmp->seg_in.hit_dist, tmp->seg_out.hit_dist);
895 #endif
896  } else {
897  /* subtract edges */
898  if (segb->seg_in.hit_dist > sega->seg_in.hit_dist)
899  sega->seg_out.hit_dist = segb->seg_in.hit_dist;
900  if (segb->seg_out.hit_dist < sega->seg_out.hit_dist)
901  sega->seg_in.hit_dist = segb->seg_out.hit_dist;
902 
903 #ifdef debug
904  bu_log("\t\tsubtracted A down to %g to %g\n", sega->seg_in.hit_dist, sega->seg_out.hit_dist);
905 #endif
906  }
907  }
908  sega = next;
909  }
910 
911  /* put the resulting ONS list on the result list */
912  BU_LIST_INSERT_LIST(&ret, &ons);
913 
914  /* add INS to the return list (maintain order) */
915  while (BU_LIST_WHILE (sega, seg, &ins)) {
916  BU_LIST_DEQUEUE(&sega->l);
917 
918  inserted = 0;
919  for (BU_LIST_FOR (segb, seg, &ret)) {
920  if (sega->seg_in.hit_dist < segb->seg_in.hit_dist) {
921  BU_LIST_INSERT(&segb->l, &sega->l);
922  inserted = 1;
923  break;
924  }
925  }
926 
927  if (!inserted)
928  BU_LIST_INSERT(&ret, &sega->l)
929  }
930 
931  MY_FREE_SEG_LIST(B, dgcdp->ap->a_resource);
932  bu_free((char *)B, "bu_list");
933  MY_FREE_SEG_LIST(A, dgcdp->ap->a_resource);
934  BU_LIST_INSERT_LIST(A, &ret)
935 
936 #ifdef debug
937  show_seg(A, "Returning");
938 #endif
939 
940  return A;
941  }
942 
943  /* should never get here */
944  MY_FREE_SEG_LIST(A, dgcdp->ap->a_resource);
945  MY_FREE_SEG_LIST(B, dgcdp->ap->a_resource);
946  bu_free((char *)B, "bu_list");
947 
948 #ifdef debug
949  show_seg(A, "Returning (default)");
950 #endif
951 
952  return A;
953 
954 }
955 
956 
957 /* evaluate an E-tree */
958 HIDDEN struct bu_list *
959 eval_etree(union E_tree *eptr,
960  struct _ged_client_data *dgcdp)
961 
962 {
963  struct bu_list *A, *B;
964 
965  CK_ETREE(eptr);
966 
967 #ifdef debug
968  bu_log("In eval_etree:\n");
969 #endif
970 
971  switch (eptr->l.op) {
972  case OP_DB_LEAF:
973  case OP_SOLID:
974  BU_ALLOC(A, struct bu_list);
975  BU_LIST_INIT(A);
976  BU_LIST_INSERT_LIST(A, &eptr->l.seghead);
977 
978 #ifdef debug
979  show_seg(A, "LEAF:");
980 #endif
981 
982  return A;
983  case OP_SUBTRACT:
984  case OP_INTERSECT:
985  case OP_UNION:
986 #ifdef debug
987  bu_log("Evaluating subtrees\n");
988 #endif
989 
990  A = eval_etree(eptr->n.left, dgcdp);
991  B = eval_etree(eptr->n.right, dgcdp);
992  return eval_op(A, eptr->n.op, B, dgcdp);
993  }
994 
995  /* should never get here */
996  return (struct bu_list *)NULL; /* for the compilers */
997 }
998 
999 
1000 HIDDEN void
1001 inverse_dir(vect_t dir, vect_t inv_dir)
1002 {
1003  /* Compute the inverse of the direction cosines */
1004  if (!ZERO(dir[X])) {
1005  inv_dir[X]=1.0/dir[X];
1006  } else {
1007  inv_dir[X] = INFINITY;
1008  dir[X] = 0.0;
1009  }
1010  if (!ZERO(dir[Y])) {
1011  inv_dir[Y]=1.0/dir[Y];
1012  } else {
1013  inv_dir[Y] = INFINITY;
1014  dir[Y] = 0.0;
1015  }
1016  if (!ZERO(dir[Z])) {
1017  inv_dir[Z]=1.0/dir[Z];
1018  } else {
1019  inv_dir[Z] = INFINITY;
1020  dir[Z] = 0.0;
1021  }
1022 }
1023 
1024 
1025 HIDDEN struct soltab *
1026 classify_seg(struct seg *segp, struct soltab *shoot, struct xray *rp, struct _ged_client_data *dgcdp)
1027 {
1028  fastf_t mid_dist;
1029  struct xray new_rp;
1030  struct ray_data rd;
1031  struct soltab *ret = IN_SOL;
1032 
1033  memset(&rd, 0, sizeof(struct ray_data));
1034 
1035  BU_ALLOC(rd.seghead, struct seg);
1036  BU_LIST_INIT(&rd.seghead->l);
1037 
1038  mid_dist = (segp->seg_in.hit_dist + segp->seg_out.hit_dist) / 2.0;
1039  VJOIN1(new_rp.r_pt, rp->r_pt, mid_dist, rp->r_dir);
1040 #ifdef debug
1041  bu_log("Classifying segment with mid_pt (%g %g %g) with respect to %s\n", V3ARGS(new_rp.r_pt), shoot->st_dp->d_namep);
1042 #endif
1043 
1044  bn_vec_ortho(new_rp.r_dir, rp->r_dir);
1045  inverse_dir(new_rp.r_dir, rd.rd_invdir);
1046 
1047  /* set up "ray_data" structure for nmg raytrace */
1048  rd.rp = &new_rp;
1049  rd.tol = &dgcdp->gedp->ged_wdbp->wdb_tol;
1050  rd.ap = dgcdp->ap;
1052  rd.classifying_ray = 0;
1053  rd.hitmiss = (struct hitmiss **)NULL;
1054  rd.stp = shoot;
1055 
1056  if (OBJ[shoot->st_id].ft_shot && OBJ[shoot->st_id].ft_shot(shoot, &new_rp, dgcdp->ap, rd.seghead)) {
1057  struct seg *seg;
1058 
1059  while (BU_LIST_WHILE (seg, seg, &rd.seghead->l)) {
1060  BU_LIST_DEQUEUE(&seg->l);
1061 #ifdef debug
1062  bu_log("dist = %g and %g\n", seg->seg_in.hit_dist,
1063  seg->seg_out.hit_dist);
1064 #endif
1065  if (ret != ON_SURF) {
1066  if (NEAR_ZERO(seg->seg_in.hit_dist, rd.tol->dist)) {
1067  ret = ON_SURF;
1068  }
1069  if (NEAR_ZERO(seg->seg_out.hit_dist, rd.tol->dist)) {
1070  ret = ON_SURF;
1071  }
1072  }
1073  RT_FREE_SEG(seg, dgcdp->ap->a_resource);
1074  }
1075  }
1076 
1077  if (ret != ON_SURF) {
1078  vect_t new_dir;
1079 
1080  VCROSS(new_dir, new_rp.r_dir, rp->r_dir);
1081  VMOVE(new_rp.r_dir, new_dir);
1082  inverse_dir(new_rp.r_dir, rd.rd_invdir);
1083  if (OBJ[shoot->st_id].ft_shot && OBJ[shoot->st_id].ft_shot(shoot, &new_rp, dgcdp->ap, rd.seghead)) {
1084  struct seg *seg;
1085 
1086  while (BU_LIST_WHILE (seg, seg, &rd.seghead->l)) {
1087  BU_LIST_DEQUEUE(&seg->l);
1088 #ifdef debug
1089  bu_log("dist = %g and %g\n", seg->seg_in.hit_dist,
1090  seg->seg_out.hit_dist);
1091 #endif
1092  if (ret != ON_SURF) {
1093  if (NEAR_ZERO(seg->seg_in.hit_dist, rd.tol->dist)) {
1094  ret = ON_SURF;
1095  }
1096  if (NEAR_ZERO(seg->seg_out.hit_dist, rd.tol->dist)) {
1097  ret = ON_SURF;
1098  }
1099  }
1100  RT_FREE_SEG(seg, dgcdp->ap->a_resource);
1101  }
1102  }
1103  }
1104 #ifdef debug
1105  bu_log("\t x%x\n", ret);
1106 #endif
1107  return ret;
1108 }
1109 
1110 
1111 /* Shoot rays (corresponding to possible edges in the result) at the
1112  * solids, put the results in the E-tree leaves as type IN_SOL. Call
1113  * eval_etree() and plot the results
1114  */
1115 HIDDEN void
1116 shoot_and_plot(point_t start_pt,
1117  vect_t dir,
1118  struct bu_list *vhead,
1119  fastf_t edge_len,
1120  int skip_leaf1,
1121  int skip_leaf2,
1122  union E_tree *eptr,
1123  struct soltab *type,
1124  struct _ged_client_data *dgcdp)
1125 {
1126  struct xray rp;
1127  struct ray_data rd;
1128  int shoot_leaf;
1129  struct bu_list *final_segs;
1130 
1132  bu_log("Error at start of shoot_and_plot()\n");
1133 
1134  CK_ETREE(eptr);
1135 
1136  memset(&rd, 0, sizeof(struct ray_data));
1137 
1138  BU_ALLOC(rd.seghead, struct seg);
1139  BU_LIST_INIT(&rd.seghead->l);
1140 
1141  VMOVE(rp.r_pt, start_pt);
1142  VMOVE(rp.r_dir, dir);
1143  /* Compute the inverse of the direction cosines */
1144  if (!ZERO(rp.r_dir[X])) {
1145  rd.rd_invdir[X]=1.0/rp.r_dir[X];
1146  } else {
1147  rd.rd_invdir[X] = INFINITY;
1148  rp.r_dir[X] = 0.0;
1149  }
1150  if (!ZERO(rp.r_dir[Y])) {
1151  rd.rd_invdir[Y]=1.0/rp.r_dir[Y];
1152  } else {
1153  rd.rd_invdir[Y] = INFINITY;
1154  rp.r_dir[Y] = 0.0;
1155  }
1156  if (!ZERO(rp.r_dir[Z])) {
1157  rd.rd_invdir[Z]=1.0/rp.r_dir[Z];
1158  } else {
1159  rd.rd_invdir[Z] = INFINITY;
1160  rp.r_dir[Z] = 0.0;
1161  }
1162 
1163  /* set up "ray_data" structure for nmg raytrace */
1164  rd.rp = &rp;
1165  rd.tol = &dgcdp->gedp->ged_wdbp->wdb_tol;
1166  rd.ap = dgcdp->ap;
1168  rd.classifying_ray = 0;
1169  rd.hitmiss = (struct hitmiss **)NULL;
1170 
1171  /* shoot this ray at every leaf solid except the one this edge
1172  * came from (or the two that this intersection line came from
1173  */
1174  for (shoot_leaf=0; shoot_leaf < BU_PTBL_END(&dgcdp->leaf_list); shoot_leaf++) {
1175  union E_tree *shoot;
1176  int dont_shoot=0;
1177 
1178  shoot = (union E_tree *)BU_PTBL_GET(&dgcdp->leaf_list, shoot_leaf);
1179 
1180  if (BU_LIST_NON_EMPTY(&shoot->l.seghead)) {
1181  MY_FREE_SEG_LIST(&shoot->l.seghead, dgcdp->ap->a_resource);
1182  }
1183  BU_LIST_INIT(&shoot->l.seghead);
1184 
1185  /* don't shoot rays at the leaves that were the source of this
1186  * possible edge.
1187  */
1188  if (shoot_leaf == skip_leaf1 || shoot_leaf == skip_leaf2)
1189  dont_shoot = 1;
1190  else {
1191  /* don't shoot at duplicate solids either */
1192  union E_tree *leaf;
1193 
1194  if (skip_leaf1 >= 0) {
1195  leaf = (union E_tree *)BU_PTBL_GET(&dgcdp->leaf_list, skip_leaf1);
1196  if (leaf->l.stp->st_dp == shoot->l.stp->st_dp) {
1197  if (!leaf->l.stp->st_matp && !shoot->l.stp->st_matp)
1198  dont_shoot = 1;
1199  else if (!leaf->l.stp->st_matp &&
1200  bn_mat_is_equal(shoot->l.stp->st_matp,
1202  &dgcdp->gedp->ged_wdbp->wdb_tol))
1203  dont_shoot = 1;
1204  else if (!shoot->l.stp->st_matp &&
1205  bn_mat_is_equal(leaf->l.stp->st_matp,
1207  &dgcdp->gedp->ged_wdbp->wdb_tol))
1208  dont_shoot = 1;
1209  else if (leaf->l.stp->st_matp &&
1210  shoot->l.stp->st_matp &&
1211  bn_mat_is_equal(leaf->l.stp->st_matp,
1212  shoot->l.stp->st_matp,
1213  &dgcdp->gedp->ged_wdbp->wdb_tol))
1214  dont_shoot = 1;
1215  }
1216  }
1217  if (!dont_shoot && skip_leaf2 >= 0) {
1218  leaf = (union E_tree *)BU_PTBL_GET(&dgcdp->leaf_list, skip_leaf2);
1219  if (leaf->l.stp->st_dp == shoot->l.stp->st_dp) {
1220  if (!leaf->l.stp->st_matp && !shoot->l.stp->st_matp)
1221  dont_shoot = 1;
1222  else if (!leaf->l.stp->st_matp &&
1223  bn_mat_is_equal(shoot->l.stp->st_matp,
1225  &dgcdp->gedp->ged_wdbp->wdb_tol))
1226  dont_shoot = 1;
1227  else if (!shoot->l.stp->st_matp &&
1228  bn_mat_is_equal(leaf->l.stp->st_matp,
1230  &dgcdp->gedp->ged_wdbp->wdb_tol))
1231  dont_shoot = 1;
1232  else if (leaf->l.stp->st_matp &&
1233  shoot->l.stp->st_matp &&
1234  bn_mat_is_equal(leaf->l.stp->st_matp,
1235  shoot->l.stp->st_matp,
1236  &dgcdp->gedp->ged_wdbp->wdb_tol))
1237  dont_shoot = 1;
1238  }
1239  }
1240  }
1241 
1242  if (dont_shoot) {
1243  struct seg *seg;
1244 
1245  /* put entire edge in seg list and mark it as ON the
1246  * surface.
1247  */
1248  RT_GET_SEG(seg, dgcdp->ap->a_resource);
1249  seg->l.magic = RT_SEG_MAGIC;
1250  seg->seg_in.hit_dist = 0.0;
1251  seg->seg_out.hit_dist = edge_len;
1252  seg->seg_stp = type;
1253  BU_LIST_INSERT(&shoot->l.seghead, &seg->l);
1254  continue;
1255  }
1256 
1257  /* initialize the lists of things that have been hit/missed */
1258  rd.rd_m = shoot->l.m;
1259  BU_LIST_INIT(&rd.rd_hit);
1260  BU_LIST_INIT(&rd.rd_miss);
1261 
1262  rd.stp = shoot->l.stp;
1263 
1264  /* actually shoot the ray, assign segments to the leaf, and
1265  * mark them as IN_SOL.
1266  */
1267  if (rt_in_rpp(&rp, rd.rd_invdir, shoot->l.stp->st_min, shoot->l.stp->st_max)) {
1268  if (OBJ[shoot->l.stp->st_id].ft_shot && OBJ[shoot->l.stp->st_id].ft_shot(shoot->l.stp, &rp, dgcdp->ap, rd.seghead)) {
1269  struct seg *seg;
1270 
1271  /* put the segments in the lead solid structure */
1272  while (BU_LIST_WHILE (seg, seg, &rd.seghead->l)) {
1273  BU_LIST_DEQUEUE(&seg->l);
1274  /* clip segments to the edge being considered */
1275  if (seg->seg_in.hit_dist >= edge_len || seg->seg_out.hit_dist <= 0) {
1276  RT_FREE_SEG(seg, dgcdp->ap->a_resource);
1277  } else {
1278  if (seg->seg_in.hit_dist < 0.0)
1279  seg->seg_in.hit_dist = 0.0;
1280  if (seg->seg_out.hit_dist > edge_len)
1281  seg->seg_out.hit_dist = edge_len;
1282  seg->seg_stp = classify_seg(seg, shoot->l.stp, &rp, dgcdp);
1283  BU_LIST_INSERT(&shoot->l.seghead, &seg->l);
1284  }
1285  }
1286  }
1287  }
1288  }
1289 
1290  /* Evaluate the Boolean tree to get the "final" segments which are
1291  * to be plotted.
1292  */
1293 #ifdef debug
1294  bu_log("EVALUATING ETREE:\n");
1295  bu_log("ray start (%g %g %g), dir=(%g %g %g)\n", V3ARGS(start_pt), V3ARGS(dir));
1296 #endif
1297 
1298  final_segs = eval_etree(eptr, dgcdp);
1299 
1300 #ifdef debug
1301  show_seg(final_segs, "DRAWING");
1302 #endif
1303 
1304  if (final_segs) {
1305  struct seg *seg;
1306 
1307  /* add the segments to the VLIST */
1308  for (BU_LIST_FOR (seg, seg, final_segs)) {
1309  point_t pt;
1310 
1311  /* only plot the resulting segments that are ON the
1312  * SURFace.
1313  */
1314  if (seg->seg_stp != ON_SURF)
1315  continue;
1316 
1317  dgcdp->nvectors++;
1318  VJOIN1(pt, rp.r_pt, seg->seg_in.hit_dist, rp.r_dir);
1319 
1320 #ifdef debug
1321  bu_log("\t\tDRAW (%g %g %g)", V3ARGS(pt));
1322 #endif
1323 
1324  RT_ADD_VLIST(vhead, pt, BN_VLIST_LINE_MOVE);
1325  VJOIN1(pt, rp.r_pt, seg->seg_out.hit_dist, rp.r_dir);
1326 
1327 #ifdef debug
1328  bu_log("<->(%g %g %g)\n", V3ARGS(pt));
1329 #endif
1330 
1331  RT_ADD_VLIST(vhead, pt, BN_VLIST_LINE_DRAW);
1332  }
1333 
1334  }
1335 
1336  if (final_segs)
1337  MY_FREE_SEG_LIST(final_segs, dgcdp->ap->a_resource);
1338  bu_free((char *)final_segs, "bu_list");
1339 
1341  bu_log("Error at end of shoot_and_plot()\n");
1342 
1343 }
1344 
1345 
1346 #define HITS_BLOCK 20
1347 
1348 HIDDEN void
1349 Eplot(union E_tree *eptr,
1350  struct bu_list *vhead,
1351  struct _ged_client_data *dgcdp)
1352 {
1353  point_t start_pt;
1354  int leaf_no;
1355  union E_tree *leaf_ptr;
1356  int hit_count1=0, hit_count2=0;
1357  point_t *hits1=NULL, *hits2=NULL;
1358  int hits_avail1=0, hits_avail2=0;
1359  int i;
1360  struct bu_list *result;
1361  struct bn_tol *tol;
1362 
1363  tol = &dgcdp->gedp->ged_wdbp->wdb_tol;
1364 
1365  CK_ETREE(eptr);
1366 
1367  /* create an edge list for each leaf solid */
1368  for (leaf_no=0; leaf_no < BU_PTBL_END(&dgcdp->leaf_list); leaf_no++) {
1369  leaf_ptr = (union E_tree *)BU_PTBL_GET(&dgcdp->leaf_list, leaf_no);
1370  CK_ETREE(leaf_ptr);
1371  if (leaf_ptr->l.op != OP_DB_LEAF && leaf_ptr->l.op != OP_SOLID) {
1372  bu_vls_printf(dgcdp->gedp->ged_result_str, "Eplot: Bad leaf node!!!\n");
1373  return;
1374  }
1375 
1376  if (leaf_ptr->l.m)
1377  nmg_edge_tabulate(&leaf_ptr->l.edge_list, &leaf_ptr->l.m->magic);
1378  else
1379  bu_ptbl_init(&leaf_ptr->l.edge_list, 1, "edge_list");
1380  }
1381 
1382  /* now plot appropriate parts of each solid */
1383 
1384  /* loop through every leaf solid */
1385  for (leaf_no=0; leaf_no < BU_PTBL_END(&dgcdp->leaf_list); leaf_no++) {
1386  int edge_no;
1387 
1388  leaf_ptr = (union E_tree *)BU_PTBL_GET(&dgcdp->leaf_list, leaf_no);
1389 
1390  if (!leaf_ptr->l.m)
1391  continue;
1392 
1393  /* do each edge of the current leaf solid */
1394  for (edge_no=0; edge_no < BU_PTBL_END(&leaf_ptr->l.edge_list); edge_no++) {
1395  struct edge *e;
1396  struct vertex_g *vg;
1397  struct vertex_g *vg2;
1398  vect_t dir;
1399  fastf_t edge_len;
1400  fastf_t inv_len;
1401 
1402  e = (struct edge *)BU_PTBL_GET(&leaf_ptr->l.edge_list, edge_no);
1403  NMG_CK_EDGE(e);
1404  vg = e->eu_p->vu_p->v_p->vg_p;
1405  NMG_CK_VERTEX_G(vg);
1406 
1407  vg2 = e->eu_p->eumate_p->vu_p->v_p->vg_p;
1408  NMG_CK_VERTEX_G(vg2);
1409 
1410  /* set up a ray from vg towards vg2 */
1411  VSUB2(dir, vg2->coord, vg->coord);
1412  edge_len = MAGNITUDE(dir);
1413  if (edge_len < tol->dist)
1414  continue;
1415  inv_len = 1.0/edge_len;
1416  VSCALE(dir, dir, inv_len);
1417  shoot_and_plot(vg->coord, dir, vhead, edge_len, leaf_no, -1, eptr, ON_SURF, dgcdp);
1418 
1419  }
1420  }
1421 
1422  hits1 = (point_t *)bu_calloc(HITS_BLOCK, sizeof(point_t), "hits");
1423  hits_avail1 = HITS_BLOCK;
1424  hits2 = (point_t *)bu_calloc(HITS_BLOCK, sizeof(point_t), "hits");
1425  hits_avail2 = HITS_BLOCK;
1426 
1427  /* Now draw solid intersection lines */
1428  for (leaf_no=0; leaf_no < BU_PTBL_END(&dgcdp->leaf_list); leaf_no++) {
1429  int leaf2;
1430 
1431  leaf_ptr = (union E_tree *)BU_PTBL_GET(&dgcdp->leaf_list, leaf_no);
1432  if (!leaf_ptr->l.m)
1433  continue;
1434 
1435  for (leaf2=leaf_no+1; leaf2 < BU_PTBL_END(&dgcdp->leaf_list); leaf2++) {
1436  union E_tree *leaf2_ptr;
1437  struct nmgregion *r1, *r2;
1438  struct shell *s1, *s2;
1439  struct faceuse *fu1, *fu2;
1440  struct face *f1, *f2;
1441  plane_t pl1, pl2;
1442  struct loopuse *lu1, *lu2;
1443  struct edgeuse *eu1, *eu2;
1444  struct vertex_g *vg1a, *vg1b, *vg2a, *vg2b;
1445  struct bu_list *A, *B;
1446 
1447  leaf2_ptr = (union E_tree *)BU_PTBL_GET(&dgcdp->leaf_list, leaf2);
1448  if (!leaf2_ptr->l.m)
1449  continue;
1450 
1451  /* find intersection lines between these two NMG's */
1452 
1453  r1 = BU_LIST_FIRST(nmgregion, &leaf_ptr->l.m->r_hd);
1454  s1 = BU_LIST_FIRST(shell, &r1->s_hd);
1455  r2 = BU_LIST_FIRST(nmgregion, &leaf2_ptr->l.m->r_hd);
1456  s2 = BU_LIST_FIRST(shell, &r2->s_hd);
1457 
1458  for (BU_LIST_FOR (fu1, faceuse, &s1->fu_hd)) {
1459  if (fu1->orientation != OT_SAME)
1460  continue;
1461 
1462  f1 = fu1->f_p;
1463  NMG_GET_FU_PLANE(pl1, fu1);
1464 
1465  for (BU_LIST_FOR (fu2, faceuse, &s2->fu_hd)) {
1466  fastf_t dist;
1467  vect_t dir;
1468  vect_t vdiff;
1469  fastf_t *dists1, *dists2;
1470  fastf_t min_dist, max_dist;
1471  int min_hit, max_hit;
1472  int done;
1473  struct seg *aseg;
1474 
1475  if (fu2->orientation != OT_SAME)
1476  continue;
1477 
1478  f2 = fu2->f_p;
1479 
1480  if (!V3RPP_OVERLAP_TOL(f2->min_pt, f2->max_pt, f1->min_pt, f1->max_pt, tol->dist))
1481  continue;
1482 
1483  NMG_GET_FU_PLANE(pl2, fu2);
1484 
1485  if (bn_coplanar(pl1, pl2, tol)) {
1486  continue;
1487  }
1488 
1489  hit_count1=0;
1490  hit_count2=0;
1491  for (BU_LIST_FOR (lu1, loopuse, &fu1->lu_hd)) {
1492  if (BU_LIST_FIRST_MAGIC(&lu1->down_hd) != NMG_EDGEUSE_MAGIC)
1493  continue;
1494 
1495  for (BU_LIST_FOR (eu1, edgeuse, &lu1->down_hd)) {
1496  vg1a = eu1->vu_p->v_p->vg_p;
1497  vg1b = eu1->eumate_p->vu_p->v_p->vg_p;
1498  VSUB2(dir, vg1b->coord, vg1a->coord);
1499 
1500  /* find intersection of this edge with fu2 */
1501 
1502  if (bn_isect_line3_plane(&dist, vg1a->coord,
1503  dir, pl2,
1504  tol) < 1)
1505  continue;
1506 
1507  if (dist < -tol->dist || dist > 1.0 + tol->dist)
1508  continue;
1509 
1510  if (hit_count1 >= hits_avail1) {
1511  hits_avail1 += HITS_BLOCK;
1512  hits1 = (point_t *)bu_realloc(hits1,
1513  hits_avail1 * sizeof(point_t), "hits1");
1514  }
1515  VJOIN1(hits1[hit_count1], vg1a->coord, dist, dir);
1516  hit_count1++;
1517  }
1518  }
1519  for (BU_LIST_FOR (lu2, loopuse, &fu2->lu_hd)) {
1520  if (BU_LIST_FIRST_MAGIC(&lu2->down_hd) != NMG_EDGEUSE_MAGIC)
1521  continue;
1522 
1523  for (BU_LIST_FOR (eu2, edgeuse, &lu2->down_hd)) {
1524  vg2a = eu2->vu_p->v_p->vg_p;
1525  vg2b = eu2->eumate_p->vu_p->v_p->vg_p;
1526  VSUB2(dir, vg2b->coord, vg2a->coord);
1527 
1528  /* find intersection of this edge with fu1 */
1529 
1530  if (bn_isect_line3_plane(&dist, vg2a->coord,
1531  dir, pl1,
1532  tol) < 1)
1533  continue;
1534 
1535  if (dist < -tol->dist || dist > 1.0 + tol->dist)
1536  continue;
1537 
1538  if (hit_count2 >= hits_avail2) {
1539  hits_avail2 += HITS_BLOCK;
1540  hits2 = (point_t *)bu_realloc(hits2,
1541  hits_avail2 * sizeof(point_t), "hits2");
1542  }
1543  VJOIN1(hits2[hit_count2], vg2a->coord, dist, dir);
1544  hit_count2++;
1545  }
1546  }
1547 
1548  if (hit_count1 < 2 || hit_count2 < 2) {
1549  /* nothing to plot */
1550  continue;
1551  }
1552 
1553  /* sort the hits on face 1 */
1554  dists1 = (fastf_t *)bu_calloc(hit_count1,
1555  sizeof(fastf_t), "dists1");
1556  dists2 = (fastf_t *)bu_calloc(hit_count2,
1557  sizeof(fastf_t), "dists2");
1558  VMOVE(start_pt, hits1[0]);
1559  dists1[0] = 0.0;
1560  min_dist = 0.0;
1561  min_hit = 0;
1562  VSUB2(dir, hits1[1], hits1[0]);
1563  dists1[1] = MAGNITUDE(dir);
1564  VUNITIZE(dir);
1565  max_dist = dists1[1];
1566  max_hit = 1;
1567  for (i = 2; i < hit_count1; i++) {
1568  VSUB2(vdiff, hits1[i], start_pt);
1569  dists1[i] = MAGNITUDE(vdiff);
1570  if (VDOT(dir, vdiff) < 0.0)
1571  dists1[i] = -dists1[i];
1572  if (dists1[i] > max_dist) {
1573  max_dist = dists1[i];
1574  max_hit = i;
1575  }
1576  if (dists1[i] < min_dist) {
1577  min_dist = dists1[i];
1578  min_hit = i;
1579  }
1580  }
1581 
1582  /* recalculate dir */
1583  VSUB2(dir, hits1[max_hit], hits1[min_hit]);
1584  VUNITIZE(dir);
1585 
1586  done = 0;
1587  while (!done) {
1588  done = 1;
1589  for (i = 1; i < hit_count1; i++) {
1590  if (dists1[i-1] > dists1[i]) {
1591  fastf_t tmp;
1592  point_t tmp_pt;
1593 
1594  done = 0;
1595  tmp = dists1[i];
1596  VMOVE(tmp_pt, hits1[i]);
1597  dists1[i] = dists1[i-1];
1598  VMOVE(hits1[i], hits1[i-1]);
1599  dists1[i-1] = tmp;
1600  VMOVE(hits1[i-1], tmp_pt);
1601  }
1602  }
1603  }
1604 
1605  /* sort the hits on face 2 */
1606  min_dist = MAX_FASTF;
1607  min_hit = -1;
1608  max_dist = -min_dist;
1609  max_hit = -1;
1610  for (i = 0; i < hit_count2; i++) {
1611  VSUB2(vdiff, hits2[i], start_pt);
1612  dists2[i] = MAGNITUDE(vdiff);
1613  if (VDOT(dir, vdiff) < 0.0)
1614  dists2[i] = -dists2[i];
1615  if (dists2[i] > max_dist) {
1616  max_dist = dists2[i];
1617  max_hit = i;
1618  }
1619  if (dists2[i] < min_dist) {
1620  min_dist = dists2[i];
1621  min_hit = i;
1622  }
1623  }
1624 
1625  done = 0;
1626  while (!done) {
1627  done = 1;
1628  for (i = 1; i < hit_count2; i++) {
1629  if (dists2[i-1] > dists2[i]) {
1630  fastf_t tmp;
1631  point_t tmp_pt;
1632 
1633  done = 0;
1634  tmp = dists2[i];
1635  VMOVE(tmp_pt, hits2[i]);
1636  dists2[i] = dists2[i-1];
1637  VMOVE(hits2[i], hits2[i-1]);
1638  dists2[i-1] = tmp;
1639  VMOVE(hits2[i-1], tmp_pt);
1640  }
1641  }
1642  }
1643 
1644  /* build a segment list for each solid */
1645  BU_ALLOC(A, struct bu_list);
1646  BU_ALLOC(B, struct bu_list);
1647  BU_LIST_INIT(A);
1648  BU_LIST_INIT(B);
1649 
1650  for (i = 1; i < hit_count1; i += 2) {
1651  fastf_t diff;
1652 
1653  diff = dists1[i] - dists1[i-1];
1654  if (NEAR_ZERO(diff, tol->dist)) {
1655  continue;
1656  }
1657  RT_GET_SEG(aseg, dgcdp->ap->a_resource);
1658  aseg->l.magic = RT_SEG_MAGIC;
1659  aseg->seg_stp = ON_INT;
1660  VMOVE(aseg->seg_in.hit_point, hits1[i-1]);
1661  aseg->seg_in.hit_dist = dists1[i-1];
1662  VMOVE(aseg->seg_out.hit_point, hits1[i]);
1663  aseg->seg_out.hit_dist = dists1[i];
1664 
1665  BU_LIST_APPEND(A, &aseg->l);
1666  }
1667 
1668  for (i = 1; i < hit_count2; i += 2) {
1669  fastf_t diff;
1670 
1671  diff = dists2[i] - dists2[i-1];
1672  if (NEAR_ZERO(diff, tol->dist)) {
1673  continue;
1674  }
1675  RT_GET_SEG(aseg, dgcdp->ap->a_resource);
1676  aseg->l.magic = RT_SEG_MAGIC;
1677  aseg->seg_stp = ON_INT;
1678  VMOVE(aseg->seg_in.hit_point, hits2[i-1]);
1679  aseg->seg_in.hit_dist = dists2[i-1];
1680  VMOVE(aseg->seg_out.hit_point, hits2[i]);
1681  aseg->seg_out.hit_dist = dists2[i];
1682 
1683  BU_LIST_APPEND(B, &aseg->l);
1684  }
1685 
1686  result = eval_op(A, OP_INTERSECT, B, dgcdp);
1687 
1688  for (BU_LIST_FOR (aseg, seg, result)) {
1689  point_t ray_start;
1690 
1691  VJOIN1(ray_start, start_pt, aseg->seg_in.hit_dist, dir);
1692  shoot_and_plot(ray_start, dir, vhead,
1693  aseg->seg_out.hit_dist - aseg->seg_in.hit_dist,
1694  leaf_no, leaf2, eptr, ON_INT, dgcdp);
1695  }
1696  MY_FREE_SEG_LIST(result, dgcdp->ap->a_resource);
1697 
1698  bu_free((char *)dists1, "dists1");
1699  bu_free((char *)dists2, "dists2");
1700  }
1701  }
1702  }
1703  }
1704 
1705  bu_free((char *)hits1, "hits1");
1706  bu_free((char *)hits2, "hits2");
1707 }
1708 
1709 
1710 HIDDEN void
1711 free_etree(union E_tree *eptr,
1712  struct _ged_client_data *dgcdp)
1713 {
1714  CK_ETREE(eptr);
1715 
1716  switch (eptr->l.op) {
1717  case OP_UNION:
1718  case OP_SUBTRACT:
1719  case OP_INTERSECT:
1720  free_etree(eptr->n.left, dgcdp);
1721  free_etree(eptr->n.right, dgcdp);
1722  bu_free((char *)eptr, "node pointer");
1723  break;
1724  case OP_DB_LEAF:
1725  case OP_SOLID:
1726  if (eptr->l.m && !eptr->l.do_not_free_model) {
1727  nmg_km(eptr->l.m);
1728  eptr->l.m = (struct model *)NULL;
1729  }
1730  if (BU_LIST_NON_EMPTY(&eptr->l.seghead)) {
1731  MY_FREE_SEG_LIST(&eptr->l.seghead, dgcdp->ap->a_resource);
1732  }
1733  if (BU_LIST_NON_EMPTY(&eptr->l.edge_list.l)) {
1734  bu_ptbl_free(&eptr->l.edge_list);
1735  }
1736  if (eptr->l.stp) {
1737  if (eptr->l.stp->st_specific && OBJ[eptr->l.stp->st_id].ft_free)
1738  OBJ[eptr->l.stp->st_id].ft_free(eptr->l.stp);
1739  bu_free((char *)eptr->l.stp, "struct soltab");
1740  }
1741 
1742  bu_free((char *)eptr, "leaf pointer");
1743  break;
1744  }
1745 }
1746 
1747 
1748 /* convert all "half" solids to polysolids */
1749 HIDDEN void
1751 {
1752  point_t max, min;
1753  int i, count=0;
1754  struct bn_tol *tol;
1755 
1756  tol = &dgcdp->gedp->ged_wdbp->wdb_tol;
1757 
1758  VSETALL(max, -INFINITY);
1759  VSETALL(min, INFINITY);
1760 
1761  for (i = 0; i < BU_PTBL_END(&dgcdp->leaf_list); i++) {
1762  union E_tree *tp;
1763 
1764  tp = (union E_tree *)BU_PTBL_GET(&dgcdp->leaf_list, i);
1765 
1766  if (tp->l.stp->st_id == ID_HALF)
1767  continue;
1768 
1769  VMINMAX(min, max, tp->l.stp->st_min);
1770  VMINMAX(min, max, tp->l.stp->st_max);
1771  count++;
1772  }
1773 
1774  if (!count) {
1775  bu_vls_printf(dgcdp->gedp->ged_result_str, "A 'half' solid is the only solid in a region (ignored)\n");
1776  return;
1777  }
1778 
1779  for (i = 0; i < BU_PTBL_END(&dgcdp->leaf_list); i++) {
1780  union E_tree *tp;
1781  struct vertex *v[8];
1782  struct vertex **vp[4];
1783  struct nmgregion *r;
1784  struct shell *s;
1785  struct rt_pg_internal *pg;
1786  struct faceuse *fu;
1787  plane_t haf_pl;
1788  struct half_specific *hp;
1789  int j;
1790 
1791  tp = (union E_tree *)BU_PTBL_GET(&dgcdp->leaf_list, i);
1792 
1793  if (tp->l.stp->st_id != ID_HALF)
1794  continue;
1795 
1796  hp = (struct half_specific *)tp->l.stp->st_specific;
1797 
1798  HMOVE(haf_pl, hp->half_eqn);
1799 
1800  if (DIST_PT_PLANE(max, haf_pl) >= -tol->dist &&
1801  DIST_PT_PLANE(min, haf_pl) >= -tol->dist)
1802  continue;
1803 
1804  /* make an NMG the size of our model bounding box */
1805  tp->l.m = nmg_mm();
1806  r = nmg_mrsv(tp->l.m);
1807  s = BU_LIST_FIRST(shell, &r->s_hd);
1808 
1809  for (j = 0; j < 8; j++)
1810  v[j] = (struct vertex *)NULL;
1811 
1812  vp[0] = &v[0];
1813  vp[1] = &v[1];
1814  vp[2] = &v[2];
1815  vp[3] = &v[3];
1816  fu = nmg_cmface(s, vp, 4);
1817  nmg_vertex_g(v[0], max[X], min[Y], min[Z]);
1818  nmg_vertex_g(v[1], max[X], max[Y], min[Z]);
1819  nmg_vertex_g(v[2], max[X], max[Y], max[Z]);
1820  nmg_vertex_g(v[3], max[X], min[Y], max[Z]);
1821  nmg_calc_face_g(fu);
1822 
1823  vp[0] = &v[4];
1824  vp[1] = &v[5];
1825  vp[2] = &v[6];
1826  vp[3] = &v[7];
1827  fu = nmg_cmface(s, vp, 4);
1828  nmg_vertex_g(v[4], min[X], min[Y], min[Z]);
1829  nmg_vertex_g(v[5], min[X], min[Y], max[Z]);
1830  nmg_vertex_g(v[6], min[X], max[Y], max[Z]);
1831  nmg_vertex_g(v[7], min[X], max[Y], min[Z]);
1832  nmg_calc_face_g(fu);
1833 
1834  vp[0] = &v[0];
1835  vp[1] = &v[3];
1836  vp[2] = &v[5];
1837  vp[3] = &v[4];
1838  fu = nmg_cmface(s, vp, 4);
1839  nmg_calc_face_g(fu);
1840 
1841  vp[0] = &v[1];
1842  vp[1] = &v[7];
1843  vp[2] = &v[6];
1844  vp[3] = &v[2];
1845  fu = nmg_cmface(s, vp, 4);
1846  nmg_calc_face_g(fu);
1847 
1848  vp[0] = &v[3];
1849  vp[1] = &v[2];
1850  vp[2] = &v[6];
1851  vp[3] = &v[5];
1852  fu = nmg_cmface(s, vp, 4);
1853  nmg_calc_face_g(fu);
1854 
1855  vp[0] = &v[1];
1856  vp[1] = &v[0];
1857  vp[2] = &v[4];
1858  vp[3] = &v[7];
1859  fu = nmg_cmface(s, vp, 4);
1860  nmg_calc_face_g(fu);
1861 
1862  nmg_region_a(r, tol);
1863 
1864  for (BU_LIST_FOR (fu, faceuse, &s->fu_hd)) {
1865  struct edgeuse *eu, *new_eu;
1866  struct loopuse *lu, *new_lu;
1867  plane_t pl;
1868  struct vertexuse *vcut[2];
1869  point_t pt[2];
1870  struct edgeuse *eu_split[2];
1871 
1872  if (fu->orientation != OT_SAME)
1873  continue;
1874 
1875  NMG_GET_FU_PLANE(pl, fu);
1876 
1877  if (bn_coplanar(pl, haf_pl, tol) > 0)
1878  continue;
1879 
1880  lu = BU_LIST_FIRST(loopuse, &fu->lu_hd);
1881 
1882  count = 0;
1883  for (BU_LIST_FOR (eu, edgeuse, &lu->down_hd)) {
1884  vect_t dir;
1885  struct vertex_g *v1g, *v2g;
1886  fastf_t dist;
1887 
1888  v1g = eu->vu_p->v_p->vg_p;
1889  v2g = eu->eumate_p->vu_p->v_p->vg_p;
1890 
1891  VSUB2(dir, v2g->coord, v1g->coord);
1892 
1893  if (bn_isect_line3_plane(&dist, v1g->coord, dir, haf_pl, tol) < 1)
1894  continue;
1895 
1896  if (dist < 0.0 || dist >=1.0)
1897  continue;
1898 
1899  VJOIN1(pt[count], v1g->coord, dist, dir);
1900  eu_split[count] = eu;
1901 
1902  count++;
1903  if (count == 2)
1904  break;
1905  }
1906 
1907  if (count != 2)
1908  continue;
1909 
1910  new_eu = nmg_eusplit((struct vertex *)NULL, eu_split[0], 1);
1911  vcut[0] = new_eu->vu_p;
1912  nmg_vertex_gv(vcut[0]->v_p, pt[0]);
1913 
1914  new_eu = nmg_eusplit((struct vertex *)NULL, eu_split[1], 1);
1915  vcut[1] = new_eu->vu_p;
1916  nmg_vertex_gv(vcut[1]->v_p, pt[1]);
1917 
1918  new_lu = nmg_cut_loop(vcut[0], vcut[1]);
1919  nmg_lu_reorient(lu);
1920  nmg_lu_reorient(new_lu);
1921 
1922  for (BU_LIST_FOR (eu, edgeuse, &lu->down_hd)) {
1923  if (eu->vu_p->v_p == vcut[0]->v_p || eu->vu_p->v_p == vcut[1]->v_p)
1924  continue;
1925 
1926  if (DIST_PT_PLANE(eu->vu_p->v_p->vg_p->coord, haf_pl) > tol->dist) {
1927  nmg_klu(lu);
1928  break;
1929  } else {
1930  nmg_klu(new_lu);
1931  break;
1932  }
1933  }
1934  }
1935 
1936  /* kill any faces outside the half */
1937  fu = BU_LIST_FIRST(faceuse, &s->fu_hd);
1938  if (fu->orientation != OT_SAME)
1939  fu = BU_LIST_PNEXT(faceuse, &fu->l);
1940  while (BU_LIST_NOT_HEAD(&fu->l, &s->fu_hd)) {
1941  struct faceuse *next_fu;
1942  struct loopuse *lu;
1943  int killfu=0;
1944 
1945  next_fu = BU_LIST_PNEXT(faceuse, &fu->l);
1946  if (fu->fumate_p == next_fu)
1947  next_fu = BU_LIST_PNEXT(faceuse, &next_fu->l);
1948 
1949  if (fu->orientation != OT_SAME) {
1950  fu = next_fu;
1951  continue;
1952  }
1953 
1954  lu = BU_LIST_FIRST(loopuse, &fu->lu_hd);
1955  while (BU_LIST_NOT_HEAD(&lu->l, &fu->lu_hd)) {
1956  struct loopuse *next_lu;
1957  struct edgeuse *eu;
1958  int killit;
1959 
1960  next_lu = BU_LIST_PNEXT(loopuse, &lu->l);
1961 
1962  killit = 0;
1963  for (BU_LIST_FOR (eu, edgeuse, &lu->down_hd)) {
1964  struct vertex_g *vg;
1965 
1966  vg = eu->vu_p->v_p->vg_p;
1967 
1968  if (DIST_PT_PLANE(vg->coord, haf_pl) > tol->dist) {
1969  killit = 1;
1970  break;
1971  }
1972  }
1973 
1974  if (killit) {
1975  if (nmg_klu(lu)) {
1976  killfu = 1;
1977  break;
1978  }
1979  }
1980  lu = next_lu;
1981  }
1982 
1983  if (killfu)
1984  nmg_kfu(fu);
1985 
1986  fu = next_fu;
1987  }
1988 
1989  nmg_rebound(tp->l.m, tol);
1990  nmg_model_fuse(tp->l.m, tol);
1991  nmg_close_shell(s, tol);
1992  nmg_rebound(tp->l.m, tol);
1993 
1994  BU_ALLOC(pg, struct rt_pg_internal);
1995 
1996  if (!nmg_to_poly(tp->l.m, pg, tol)) {
1997  bu_free((char *)pg, "rt_pg_internal");
1998  bu_vls_printf(dgcdp->gedp->ged_result_str, "Prep failure for solid '%s'\n", tp->l.stp->st_dp->d_namep);
1999  } else {
2000  struct rt_db_internal intern2;
2001 
2002  RT_DB_INTERNAL_INIT(&intern2);
2003  intern2.idb_major_type = DB5_MAJORTYPE_BRLCAD;
2004  intern2.idb_type = ID_POLY;
2005  intern2.idb_meth = &OBJ[ID_POLY];
2006  intern2.idb_ptr = (void *)pg;
2007  if (OBJ[tp->l.stp->st_id].ft_free)
2008  OBJ[tp->l.stp->st_id].ft_free(tp->l.stp);
2009  tp->l.stp->st_specific = NULL;
2010  tp->l.stp->st_id = ID_POLY;
2011  VSETALL(tp->l.stp->st_max, -INFINITY);
2012  VSETALL(tp->l.stp->st_min, INFINITY);
2013  if (rt_obj_prep(tp->l.stp, &intern2, dgcdp->rtip) < 0) {
2015  "Prep failure for polysolid version of solid '%s'",
2016  tp->l.stp->st_dp->d_namep);
2017  }
2018 
2019  rt_db_free_internal(&intern2);
2020  }
2021  }
2022 }
2023 
2024 
2025 int
2026 ged_E(struct ged *gedp, int argc, const char *argv[])
2027 {
2028  int i;
2029  int c;
2030  int ac = 1;
2031  char *av[2];
2032  struct _ged_client_data *dgcdp;
2033  static const char *usage = "[-C#/#/# -s] objects(s)";
2034 
2037  GED_CHECK_ARGC_GT_0(gedp, argc, GED_ERROR);
2038 
2039  /* initialize result */
2040  bu_vls_trunc(gedp->ged_result_str, 0);
2041 
2042  /* must be wanting help */
2043  if (argc == 1) {
2044  bu_vls_printf(gedp->ged_result_str, "Usage: %s %s", argv[0], usage);
2045  return GED_HELP;
2046  }
2047 
2049  bu_log("Error at start of 'E'\n");
2050 
2051  /* XXX: where is this released? */
2052  BU_ALLOC(dgcdp, struct _ged_client_data);
2053  dgcdp->gedp = gedp;
2054  dgcdp->do_polysolids = 0;
2055  dgcdp->wireframe_color_override = 0;
2056  dgcdp->transparency = 0;
2057  dgcdp->dmode = _GED_BOOL_EVAL;
2058  dgcdp->freesolid = gedp->freesolid;
2059 
2060  /* Parse options. */
2061  bu_optind = 1; /* re-init bu_getopt() */
2062  while ((c=bu_getopt(argc, (char * const *)argv, "sC:")) != -1) {
2063  switch (c) {
2064  case 'C':
2065  {
2066  int r, g, b;
2067  char *cp = bu_optarg;
2068 
2069  r = atoi(cp);
2070  while ((*cp >= '0' && *cp <= '9')) cp++;
2071  while (*cp && (*cp < '0' || *cp > '9')) cp++;
2072  g = atoi(cp);
2073  while ((*cp >= '0' && *cp <= '9')) cp++;
2074  while (*cp && (*cp < '0' || *cp > '9')) cp++;
2075  b = atoi(cp);
2076 
2077  if (r < 0 || r > 255) r = 255;
2078  if (g < 0 || g > 255) g = 255;
2079  if (b < 0 || b > 255) b = 255;
2080 
2081  dgcdp->wireframe_color_override = 1;
2082  dgcdp->wireframe_color[0] = r;
2083  dgcdp->wireframe_color[1] = g;
2084  dgcdp->wireframe_color[2] = b;
2085  }
2086  break;
2087  case 's':
2088  dgcdp->do_polysolids = 1;
2089  break;
2090  default:
2091  {
2092  bu_vls_printf(gedp->ged_result_str, "Usage: %s %s", argv[0], usage);
2093  return GED_ERROR;
2094  }
2095  }
2096  }
2097  argc -= bu_optind;
2098  argv += bu_optind;
2099 
2100  av[1] = (char *)0;
2101  for (i = 0; i < argc; ++i) {
2103  dgcdp->gdlp = dl_addToDisplay(gedp->ged_gdp->gd_headDisplay, gedp->ged_wdbp->dbip, argv[i]);
2104 
2105  BU_ALLOC(dgcdp->ap, struct application);
2106  RT_APPLICATION_INIT(dgcdp->ap);
2107  dgcdp->ap->a_resource = &rt_uniresource;
2111 
2112  bu_ptbl_init(&dgcdp->leaf_list, 8, "leaf_list");
2113 
2114  dgcdp->rtip = rt_new_rti(gedp->ged_wdbp->dbip);
2115  dgcdp->rtip->rti_tol = gedp->ged_wdbp->wdb_tol; /* struct copy */
2116  dgcdp->rtip->useair = 1;
2117  dgcdp->ap->a_rt_i = dgcdp->rtip;
2118 
2119  dgcdp->nvectors = 0;
2120  (void)time(&dgcdp->start_time);
2121 
2122  av[0] = (char *)argv[i];
2123  if (rt_gettrees(dgcdp->rtip, ac, (const char **)av, 1)) {
2124  bu_ptbl_free(&dgcdp->leaf_list);
2125 
2126  /* do not do an rt_free_rti() (closes the database!!!!) */
2127  rt_clean(dgcdp->rtip);
2128 
2129  bu_free((char *)dgcdp->rtip, "rt_i structure for 'E'");
2130  bu_free(dgcdp, "dgcdp");
2131 
2132  bu_vls_printf(gedp->ged_result_str, "Failed to get objects\n");
2133  return GED_ERROR;
2134  }
2135  {
2136  struct region *rp;
2137  union E_tree *eptr;
2138  struct bu_list vhead;
2139  struct db_tree_state ts;
2140  struct db_full_path path;
2141 
2142  BU_LIST_INIT(&vhead);
2143 
2144  for (BU_LIST_FOR (rp, region, &(dgcdp->rtip->HeadRegion))) {
2145  dgcdp->num_halfs = 0;
2146  eptr = build_etree(rp->reg_treetop, dgcdp);
2147 
2148  if (dgcdp->num_halfs)
2149  fix_halfs(dgcdp);
2150 
2151  Eplot(eptr, &vhead, dgcdp);
2152  free_etree(eptr, dgcdp);
2153  bu_ptbl_reset(&dgcdp->leaf_list);
2154  ts.ts_mater = rp->reg_mater;
2155  db_string_to_path(&path, gedp->ged_wdbp->dbip, rp->reg_name);
2156  _ged_drawH_part2(0, &vhead, &path, &ts, dgcdp);
2157  db_free_full_path(&path);
2158  }
2159  /* do not do an rt_free_rti() (closes the database!!!!) */
2160  rt_clean(dgcdp->rtip);
2161 
2162  bu_free((char *)dgcdp->rtip, "rt_i structure for 'E'");
2163  }
2164  }
2165 
2166  (void)time(&dgcdp->etime);
2167 
2168  /* free leaf_list */
2169  bu_ptbl_free(&dgcdp->leaf_list);
2170 
2171  bu_vls_printf(gedp->ged_result_str, "E: %ld vectors in %ld sec\n",
2172  dgcdp->nvectors, (long)(dgcdp->etime - dgcdp->start_time));
2173 
2174  return GED_OK;
2175 }
2176 
2177 
2178 /*
2179  * Local Variables:
2180  * mode: C
2181  * tab-width: 8
2182  * indent-tabs-mode: t
2183  * c-file-style: "stroustrup"
2184  * End:
2185  * ex: shiftwidth=4 tabstop=8
2186  */
void usage(struct ged *gedp)
Definition: coil.c:315
#define GED_OK
Definition: ged.h:55
#define ON_SURF
Definition: bigE.c:50
int wireframe_color_override
Definition: ged_private.h:104
char * d_namep
pointer to name string
Definition: raytrace.h:859
#define BU_LIST_FOR(p, structure, hp)
Definition: list.h:365
struct rt_i * rtip
Definition: ged_private.h:125
void nmg_lu_reorient(struct loopuse *lu)
Definition: nmg_mod.c:3649
const struct bn_tol * tol
Definition: raytrace.h:2421
#define NMG_EDGEUSE_MAGIC
Definition: magic.h:120
int nmg_model_fuse(struct model *m, const struct bn_tol *tol)
Definition: nmg_fuse.c:1919
void bu_log(const char *,...) _BU_ATTR_PRINTF12
Definition: log.c:176
#define BU_LIST_INSERT(old, new)
Definition: list.h:183
int rt_db_get_internal(struct rt_db_internal *ip, const struct directory *dp, const struct db_i *dbip, const mat_t mat, struct resource *resp)
Definition: dir.c:76
int bn_isect_line3_plane(fastf_t *dist, const point_t pt, const vect_t dir, const plane_t plane, const struct bn_tol *tol)
struct hit seg_in
IN information.
Definition: raytrace.h:370
void nmg_close_shell(struct shell *s, const struct bn_tol *tol)
Definition: nmg_misc.c:2256
struct rt_bot_internal * nmg_bot(struct shell *s, const struct bn_tol *tol)
Definition: nmg_misc.c:10826
struct mater_info ts_mater
material properties
Definition: raytrace.h:1047
Definition: list.h:118
const struct directory * st_dp
Directory entry of solid.
Definition: raytrace.h:436
#define BU_DEBUG_MEM_CHECK
Definition: debug.h:54
void rt_clean(struct rt_i *rtip)
int nmg_kfu(struct faceuse *fu1)
Definition: nmg_mk.c:1207
#define RT_FREE_SEG(p, res)
Definition: raytrace.h:389
#define OP_NOP
Leaf with no effect.
Definition: raytrace.h:1132
int bn_coplanar(const plane_t a, const plane_t b, const struct bn_tol *tol)
Test if two planes are identical. If so, their dot products will be either +1 or -1, with the distance from the origin equal in magnitude.
union E_tree * left
Definition: bigE.c:82
double dist
>= 0
Definition: tol.h:73
Definition: ged.h:338
vect_t half_Xbase
Definition: half.c:58
const mat_t bn_mat_identity
Matrix and vector functionality.
Definition: mat.c:46
struct db_i * dbip
Definition: raytrace.h:1266
struct soltab * seg_stp
pointer back to soltab
Definition: raytrace.h:372
if lu s
Definition: nmg_mod.c:3860
int useair
1="air" regions are retained while prepping
Definition: raytrace.h:1756
void bu_ptbl_init(struct bu_ptbl *b, size_t len, const char *str)
Definition: ptbl.c:32
struct soltab * stp
Definition: raytrace.h:2420
#define RT_SOLTAB2_MAGIC
Definition: magic.h:168
lu
Definition: nmg_mod.c:3855
#define VSETALL(a, s)
Definition: color.c:54
struct bu_list HeadRegion
ptr of list of regions in model
Definition: raytrace.h:1778
Definition: raytrace.h:215
void bu_vls_trunc(struct bu_vls *vp, int len)
Definition: vls.c:198
#define ID_BOT
Bag o' triangles.
Definition: raytrace.h:488
#define BU_LIST_IS_EMPTY(hp)
Definition: list.h:295
#define GED_CHECK_ARGC_GT_0(_gedp, _argc, _flags)
Definition: ged.h:202
struct directory * db_lookup(const struct db_i *, const char *name, int noisy)
Definition: db_lookup.c:153
Definition: raytrace.h:368
#define BU_LIST_IS_INITIALIZED(_hp)
Definition: list.h:175
void nmg_vertex_gv(struct vertex *v, const fastf_t *pt)
Definition: nmg_mk.c:1668
struct solid * freesolid
Definition: ged_private.h:121
#define RT_CK_COMB(_p)
Definition: raytrace.h:955
uint32_t magic
Definition: raytrace.h:2413
struct display_list * dl_addToDisplay(struct bu_list *hdlp, struct db_i *dbip, const char *name)
Definition: display_list.c:42
vect_t half_Ybase
Definition: half.c:59
void nmg_rebound(struct model *m, const struct bn_tol *tol)
Definition: nmg_misc.c:2072
struct bu_list rd_hit
list of hit elements
Definition: raytrace.h:2423
struct bu_list re_nmgfree
head of NMG hitmiss freelist
Definition: raytrace.h:1454
Definition: bigE.c:75
struct rt_wdb * ged_wdbp
Definition: ged.h:340
char * bu_optarg
Definition: globals.c:91
Header file for the BRL-CAD common definitions.
int nmg_to_poly(const struct model *m, struct rt_pg_internal *poly_int, const struct bn_tol *tol)
Definition: nmg_misc.c:9824
int bu_optind
Definition: globals.c:89
#define CK_ETREE(_p)
Definition: bigE.c:104
HIDDEN void Eplot(union E_tree *eptr, struct bu_list *vhead, struct _ged_client_data *dgcdp)
Definition: bigE.c:1349
matp_t st_matp
solid coords to model space, NULL=identity
Definition: raytrace.h:441
long time(time_t *)
struct bu_list seghead
Definition: bigE.c:91
HIDDEN struct soltab * classify_seg(struct seg *segp, struct soltab *shoot, struct xray *rp, struct _ged_client_data *dgcdp)
Definition: bigE.c:1026
void(* ged_free_vlist_callback)(unsigned int, int)
function to call after freeing a vlist
Definition: ged.h:371
const char * reg_name
Identifying string.
Definition: raytrace.h:539
#define BU_LIST_APPEND(old, new)
Definition: list.h:197
HIDDEN void free_etree(union E_tree *eptr, struct _ged_client_data *dgcdp)
Definition: bigE.c:1711
int bu_ptbl_ins(struct bu_ptbl *b, long *p)
struct resource * a_resource
dynamic memory resources
Definition: raytrace.h:1591
#define ID_COMBINATION
Combination Record.
Definition: raytrace.h:499
int rt_in_rpp(struct xray *rp, const fastf_t *invdir, const fastf_t *min, const fastf_t *max)
#define BU_LIST_NON_EMPTY(hp)
Definition: list.h:296
int bu_getopt(int nargc, char *const nargv[], const char *ostr)
Definition: getopt.c:43
struct loopuse * nmg_cut_loop(struct vertexuse *vu1, struct vertexuse *vu2)
Definition: nmg_mod.c:2283
int wireframe_color[3]
Definition: ged_private.h:105
#define MAX_FASTF
Definition: defines.h:340
struct bu_list * gd_headDisplay
head of display list
Definition: ged.h:307
struct bu_list l
links, headed by rti_headsolid
Definition: raytrace.h:426
void bu_ptbl_reset(struct bu_ptbl *b)
Definition: ptbl.c:49
struct rt_tess_tol wdb_ttol
Definition: raytrace.h:1268
#define GED_ERROR
Definition: ged.h:61
#define HIDDEN
Definition: common.h:86
int nmg_calc_face_g(struct faceuse *fu)
Definition: nmg_misc.c:1786
struct f2 f2
BU_LIST_DEQUEUE & eu1
Definition: nmg_mod.c:3839
union tree * tb_left
Definition: raytrace.h:1149
struct bu_list l
Definition: raytrace.h:369
struct soltab * tu_stp
Definition: raytrace.h:1156
uint32_t magic
Definition: bigE.c:80
int op
Definition: bigE.c:81
Definition: ptbl.h:62
struct solid * freesolid
Definition: ged.h:345
HIDDEN void eliminate_overlaps(struct bu_list *seghead, struct _ged_client_data *dgcdp)
Definition: bigE.c:305
int idb_major_type
Definition: raytrace.h:192
unsigned char do_not_free_model
Definition: bigE.c:94
int bn_mat_is_equal(const mat_t a, const mat_t b, const struct bn_tol *tol)
Definition: mat.c:925
#define OP_SUBTRACT
Binary: L subtract R.
Definition: raytrace.h:1129
uint32_t re_magic
Magic number.
Definition: raytrace.h:1441
Definition: color.c:49
struct rt_i * a_rt_i
this librt instance
Definition: raytrace.h:1588
void * memset(void *s, int c, size_t n)
struct ged * gedp
Definition: ged_private.h:102
#define OP_INTERSECT
Binary: L intersect R.
Definition: raytrace.h:1128
struct resource rt_uniresource
default. Defined in librt/globals.c
Definition: globals.c:41
#define BU_LIST_IS_HEAD(p, hp)
Definition: list.h:322
#define GED_CHECK_DATABASE_OPEN(_gedp, _flags)
Definition: ged.h:114
#define BU_LIST_PLAST(structure, p)
Definition: list.h:424
#define RT_ADD_VLIST(hd, pnt, draw)
Definition: raytrace.h:1865
#define OP_DB_LEAF
Leaf of combination, db fmt.
Definition: raytrace.h:1139
struct hitmiss ** hitmiss
1 struct hitmiss ptr per elem.
Definition: raytrace.h:2422
#define RESOURCE_MAGIC
Definition: magic.h:210
#define IN_SOL
Definition: bigE.c:51
union E_tree * build_etree(union tree *tp, struct _ged_client_data *dgcdp)
Definition: bigE.c:227
#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 _GED_BOOL_EVAL
Definition: ged_private.h:61
void _ged_drawH_part2(int dashflag, struct bu_list *vhead, const struct db_full_path *pathp, struct db_tree_state *tsp, struct _ged_client_data *dgcdp)
Definition: draw.c:164
struct model * rd_m
Definition: raytrace.h:2414
int db_string_to_path(struct db_full_path *pp, const struct db_i *dbip, const char *str)
Definition: db_fullpath.c:361
HIDDEN void inverse_dir(vect_t dir, vect_t inv_dir)
Definition: bigE.c:1001
void nmg_vertex_g(register struct vertex *v, fastf_t x, fastf_t y, fastf_t z)
Definition: nmg_mk.c:1699
#define BU_PTBL_GET(ptbl, i)
Definition: ptbl.h:108
#define RT_DB_INTERNAL_INIT(_p)
Definition: raytrace.h:199
int(* ft_shot)(struct soltab *stp, struct xray *rp, struct application *ap, struct seg *seghead)
Definition: raytrace.h:2052
#define BN_VLIST_LINE_MOVE
Definition: vlist.h:82
const struct rt_functab * idb_meth
for ft_ifree(), etc.
Definition: raytrace.h:194
#define NMG_RAY_DATA_MAGIC
Definition: magic.h:135
#define ID_NMG
n-Manifold Geometry solid
Definition: raytrace.h:469
struct display_list * gdlp
Definition: ged_private.h:103
#define V3ARGS(a)
Definition: color.c:56
void db_free_full_path(struct db_full_path *pp)
Definition: db_fullpath.c:473
#define NEAR_ZERO(val, epsilon)
Definition: color.c:55
HIDDEN union E_tree * add_solid(const struct directory *dp, matp_t mat, struct _ged_client_data *dgcdp)
Definition: bigE.c:108
void nmg_km(struct model *m)
Definition: nmg_mk.c:1634
struct f1 f1
struct model * m
Definition: bigE.c:90
point_t hit_point
DEPRECATED: Intersection point, use VJOIN1 hit_dist.
Definition: raytrace.h:251
point_t st_max
max X, Y, Z of bounding RPP
Definition: raytrace.h:438
vect_t rd_invdir
Definition: raytrace.h:2416
void dl_erasePathFromDisplay(struct bu_list *hdlp, struct db_i *dbip, void(*callback)(unsigned int, int), const char *path, int allow_split, struct solid *freesolid)
Definition: display_list.c:204
struct hit seg_out
OUT information.
Definition: raytrace.h:371
struct E_tree::E_leaf l
matp_t tl_mat
xform matp, NULL ==> identity
Definition: raytrace.h:1173
#define BN_VLIST_LINE_DRAW
Definition: vlist.h:83
#define NOT_SEG_OVERLAP(_a, _b)
Definition: bigE.c:54
struct E_tree::E_node n
plane_t half_eqn
Definition: half.c:57
void nmg_edge_tabulate(struct bu_ptbl *tab, const uint32_t *magic_p)
Definition: nmg_info.c:2138
char * tl_name
Name of this leaf (bu_strdup'ed)
Definition: raytrace.h:1174
#define BU_LIST_PNEXT(structure, p)
Definition: list.h:422
struct bu_list l
Definition: ptbl.h:63
struct tree::tree_node tr_b
#define RT_SOLTAB_MAGIC
Definition: magic.h:169
#define GED_CHECK_DRAWABLE(_gedp, _flags)
Definition: ged.h:129
void * bu_realloc(void *ptr, size_t siz, const char *str)
#define E_TREE_MAGIC
Definition: bigE.c:103
void show_seg(struct bu_list *seg, int str)
Definition: bigE.c:275
Support for uniform tolerances.
Definition: tol.h:71
#define BU_LIST_FIRST_MAGIC(hp)
Definition: list.h:416
#define ID_HALF
Half-space.
Definition: raytrace.h:464
struct bu_vls * ged_result_str
Definition: ged.h:357
uint32_t magic
Magic # for mem id/check.
Definition: list.h:119
#define BU_LIST_WHILE(p, structure, hp)
Definition: list.h:410
struct nmgregion * nmg_mrsv(struct model *m)
Definition: nmg_mk.c:306
#define HITS_BLOCK
Definition: bigE.c:1346
struct bu_ptbl edge_list
Definition: bigE.c:92
int bu_mem_barriercheck(void)
Definition: malloc.c:660
vect_t r_dir
Direction of ray (UNIT Length)
Definition: raytrace.h:219
struct ged_drawable * ged_gdp
Definition: ged.h:360
void bu_ptbl_free(struct bu_ptbl *b)
Definition: ptbl.c:226
struct bn_tol rti_tol
Math tolerances for this model.
Definition: raytrace.h:1765
struct rt_i * rt_new_rti(struct db_i *dbip)
Definition: prep.c:58
int classifying_ray
Definition: raytrace.h:2455
int rt_obj_prep(struct soltab *stp, struct rt_db_internal *ip, struct rt_i *rtip)
Definition: obj_prep.c:27
#define RT_GET_SEG(p, res)
Definition: raytrace.h:379
struct model * nmg_mm(void)
Definition: nmg_mk.c:235
fastf_t transparency
Definition: ged_private.h:118
struct tree::tree_db_leaf tr_l
uint32_t magic
Definition: bigE.c:88
struct mater_info reg_mater
Real material information.
Definition: raytrace.h:546
union tree * tb_right
Definition: raytrace.h:1150
#define ZERO(val)
Definition: units.c:38
struct soltab * stp
Definition: bigE.c:93
int bu_debug
Definition: globals.c:87
#define BU_LIST_INIT(_hp)
Definition: list.h:148
#define MY_FREE_SEG_LIST(_segheadp, _res)
Definition: bigE.c:57
void * idb_ptr
Definition: raytrace.h:195
point_t r_pt
Point at which ray starts.
Definition: raytrace.h:218
int nmg_klu(struct loopuse *lu1)
Definition: nmg_mk.c:1277
point_t st_min
min X, Y, Z of bounding RPP
Definition: raytrace.h:437
#define RT_SEG_MAGIC
Definition: magic.h:167
struct bn_tol wdb_tol
Definition: raytrace.h:1269
const struct rt_functab OBJ[]
Definition: table.c:159
#define BU_PTBL_END(ptbl)
Definition: ptbl.h:106
void bn_vec_ortho(vect_t out, const vect_t in)
HIDDEN struct bu_list * eval_etree(union E_tree *eptr, struct _ged_client_data *dgcdp)
Definition: bigE.c:959
struct bu_list l2
links, headed by st_dp->d_use_hd
Definition: raytrace.h:427
union tree * tree
Leading to tree_db_leaf leaves.
Definition: raytrace.h:938
int ged_E(struct ged *gedp, int argc, const char *argv[])
Definition: bigE.c:2026
#define ID_POLY
Polygonal faceted object.
Definition: raytrace.h:466
void bu_vls_printf(struct bu_vls *vls, const char *fmt,...) _BU_ATTR_PRINTF23
Definition: vls.c:694
#define RT_DIR_NULL
Definition: raytrace.h:875
#define LOOKUP_NOISY
Definition: raytrace.h:892
void * st_specific
-> ID-specific (private) struct
Definition: raytrace.h:435
int op
Definition: bigE.c:89
union tree * reg_treetop
Pointer to boolean tree.
Definition: raytrace.h:540
#define ON_INT
Definition: bigE.c:52
#define GED_HELP
Definition: ged.h:62
#define A
Definition: msr.c:51
void(* ft_free)(struct soltab *)
Definition: raytrace.h:2093
HIDDEN void promote_ints(struct bu_list *head, struct _ged_client_data *dgcdp)
Definition: bigE.c:436
Definition: color.c:51
int rt_gettrees(struct rt_i *rtip, int argc, const char **argv, int ncpus)
Definition: tree.c:888
void bu_free(void *ptr, const char *str)
Definition: malloc.c:328
struct xray * rp
Definition: raytrace.h:2417
#define RT_CK_TREE(_p)
Definition: raytrace.h:1182
struct application * ap
Definition: raytrace.h:2418
#define OP_SOLID
Leaf: tr_stp -> solid.
Definition: raytrace.h:1126
struct faceuse * nmg_cmface(struct shell *s, struct vertex ***verts, int n)
Definition: nmg_mod.c:979
uint32_t magic
Definition: bigE.c:76
HIDDEN void do_intersect(struct seg *A, struct seg *B, struct bu_list *seghead, struct soltab *type, struct _ged_client_data *dgcdp)
Definition: bigE.c:343
const struct rt_functab * st_meth
pointer to per-solid methods
Definition: raytrace.h:428
struct bu_list rd_miss
list of missed/sub-hit elements
Definition: raytrace.h:2424
HIDDEN void do_subtract(struct seg *A, struct seg *B, struct bu_list *seghead, struct _ged_client_data *dgcdp)
Definition: bigE.c:386
int st_id
Solid ident.
Definition: raytrace.h:431
#define BU_LIST_DEQUEUE(cur)
Definition: list.h:209
#define RT_APPLICATION_INIT(_p)
Definition: raytrace.h:1676
fastf_t hit_dist
dist from r_pt to hit_point
Definition: raytrace.h:250
#define BU_LIST_INSERT_LIST(dest_hp, src_hp)
Definition: list.h:270
struct application * ap
Definition: ged_private.h:123
void bu_bomb(const char *str) _BU_ATTR_NORETURN
Definition: bomb.c:91
double fastf_t
Definition: defines.h:300
#define OP_UNION
Binary: L union R.
Definition: raytrace.h:1127
eu2
Definition: nmg_mod.c:3875
struct seg * seghead
Definition: raytrace.h:2419
HIDDEN void shoot_and_plot(point_t start_pt, vect_t dir, struct bu_list *vhead, fastf_t edge_len, int skip_leaf1, int skip_leaf2, union E_tree *eptr, struct soltab *type, struct _ged_client_data *dgcdp)
Definition: bigE.c:1116
#define BU_LIST_NOT_HEAD(p, hp)
Definition: list.h:324
struct tree::tree_leaf tr_a
struct bu_ptbl leaf_list
Definition: ged_private.h:124
void rt_db_free_internal(struct rt_db_internal *ip)
Definition: dir.c:216
Definition: color.c:50
HIDDEN void fix_halfs(struct _ged_client_data *dgcdp)
Definition: bigE.c:1750
#define BU_LIST_FIRST(structure, hp)
Definition: list.h:312
union E_tree * right
Definition: bigE.c:83
HIDDEN struct bu_list * eval_op(struct bu_list *A, int op, struct bu_list *B, struct _ged_client_data *dgcdp)
Definition: bigE.c:637
void nmg_region_a(struct nmgregion *r, const struct bn_tol *tol)
Definition: nmg_mk.c:2557