BRL-CAD
nmg_plot.c
Go to the documentation of this file.
1 /* N M G _ P L O T . C
2  * BRL-CAD
3  *
4  * Copyright (c) 1993-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 nmg */
21 /** @{ */
22 /** @file primitives/nmg/nmg_plot.c
23  *
24  * This file contains routines that create VLISTs and UNIX-plot files.
25  * Some routines are essential to the MGED interface, some are more
26  * for diagnostic and visualization purposes.
27  *
28  * There are several distinct families:
29  *
30  * nmg_ENTITY_to_vlist - Wireframes & polygons. For MGED "ev".
31  * nmg_pl_ENTITY - Fancy edgeuse drawing, to plot file.
32  * nmg_vlblock_ENTITY - Fancy edgeuse drawing, into vlblocks.
33  * show_broken_ENTITY - Graphical display of classifier results.
34  * ...as well as assorted wrappers for debugging use.
35  *
36  * In the interest of having only a single way of creating the fancy
37  * drawings, the code is migrating to creating everything first as
38  * VLBLOCKS, and converting that to UNIX-plot files or other formats
39  * as appropriate.
40  */
41 /** @} */
42 
43 #include "common.h"
44 
45 #include <stdlib.h>
46 #include <string.h>
47 #include <signal.h>
48 #include "bio.h"
49 
50 #include "vmath.h"
51 #include "nmg.h"
52 #include "raytrace.h"
53 #include "nurb.h"
54 #include "plot3.h"
55 
56 
57 #define US_DELAY 10 /* Additional delay between frames */
58 
59 
60 /************************************************************************
61  * *
62  * NMG to VLIST routines, for MGED "ev" command. *
63  * XXX should take a flags array, to ensure each item done only once! *
64  * *
65  ************************************************************************/
66 
67 /**
68  * Plot a single vertexuse
69  */
70 void
71 nmg_vu_to_vlist(struct bu_list *vhead, const struct vertexuse *vu)
72 {
73  struct vertex *v;
74  register struct vertex_g *vg;
75 
76  BU_CK_LIST_HEAD(vhead);
77  NMG_CK_VERTEXUSE(vu);
78  v = vu->v_p;
79  NMG_CK_VERTEX(v);
80  vg = v->vg_p;
81  if (vg) {
82  /* Only thing in this shell is a point */
83  NMG_CK_VERTEX_G(vg);
84  RT_ADD_VLIST(vhead, vg->coord, BN_VLIST_LINE_MOVE);
85  RT_ADD_VLIST(vhead, vg->coord, BN_VLIST_LINE_DRAW);
86  }
87 }
88 
89 
90 /**
91  * Plot a list of edgeuses. The last edge is joined back to the first.
92  */
93 void
94 nmg_eu_to_vlist(struct bu_list *vhead, const struct bu_list *eu_hd)
95 {
96  struct edgeuse *eu;
97  struct edgeuse *eumate;
98  struct vertexuse *vu;
99  struct vertexuse *vumate;
100  register struct vertex_g *vg;
101  register struct vertex_g *vgmate;
102 
103  BU_CK_LIST_HEAD(vhead);
104 
105  /* Consider all the edges in the wire edge list */
106  for (BU_LIST_FOR(eu, edgeuse, eu_hd)) {
107  /* This wire edge runs from vertex to mate's vertex */
108  NMG_CK_EDGEUSE(eu);
109  vu = eu->vu_p;
110  NMG_CK_VERTEXUSE(vu);
111  NMG_CK_VERTEX(vu->v_p);
112  vg = vu->v_p->vg_p;
113 
114  eumate = eu->eumate_p;
115  NMG_CK_EDGEUSE(eumate);
116  vumate = eumate->vu_p;
117  NMG_CK_VERTEXUSE(vumate);
118  NMG_CK_VERTEX(vumate->v_p);
119  vgmate = vumate->v_p->vg_p;
120 
121  if (!vg || !vgmate) {
122  bu_log("nmg_eu_to_vlist() no vg or mate?\n");
123  continue;
124  }
125  NMG_CK_VERTEX_G(vg);
126  NMG_CK_VERTEX_G(vgmate);
127 
128  RT_ADD_VLIST(vhead, vg->coord, BN_VLIST_LINE_MOVE);
129  RT_ADD_VLIST(vhead, vgmate->coord, BN_VLIST_LINE_DRAW);
130  }
131 }
132 
133 
134 /**
135  * Plot a single loopuse into a bn_vlist chain headed by vhead.
136  *
137  * Needs to be able to handle both linear edges and cnurb edges.
138  */
139 void
140 nmg_lu_to_vlist(struct bu_list *vhead, const struct loopuse *lu, int poly_markers, const vectp_t normal)
141 
142 
143 /* bit vector! */
144 
145 {
146  const struct edgeuse *eu;
147  const struct vertexuse *vu;
148  const struct vertex *v;
149  register const struct vertex_g *vg;
150  const struct vertex_g *first_vg;
151  const struct vertexuse *first_vu;
152  int isfirst;
153  point_t centroid;
154  int npoints;
155 
156  BU_CK_LIST_HEAD(vhead);
157 
158  NMG_CK_LOOPUSE(lu);
159  if (BU_LIST_FIRST_MAGIC(&lu->down_hd)==NMG_VERTEXUSE_MAGIC) {
160  /* Process a loop of a single vertex */
161  vu = BU_LIST_FIRST(vertexuse, &lu->down_hd);
162  nmg_vu_to_vlist(vhead, vu);
163  return;
164  }
165 
166  /* Consider all the edges in the loop */
167  isfirst = 1;
168  first_vg = (struct vertex_g *)0;
169  first_vu = (struct vertexuse *)0;
170  npoints = 0;
171  VSETALL(centroid, 0);
172  for (BU_LIST_FOR(eu, edgeuse, &lu->down_hd)) {
173 
174  /* Consider this edge */
175  NMG_CK_EDGEUSE(eu);
176  vu = eu->vu_p;
177  NMG_CK_VERTEXUSE(vu);
178  v = vu->v_p;
179  NMG_CK_VERTEX(v);
180  vg = v->vg_p;
181  if (!vg) {
182  continue;
183  }
184  NMG_CK_VERTEX_G(vg);
185  VADD2(centroid, centroid, vg->coord);
186  npoints++;
187  if (isfirst) {
188  if (poly_markers & NMG_VLIST_STYLE_POLYGON) {
189  /* Insert a "start polygon, normal" marker */
190  RT_ADD_VLIST(vhead, normal, BN_VLIST_POLY_START);
191  if (poly_markers & NMG_VLIST_STYLE_USE_VU_NORMALS
192  && vu->a.magic_p) {
193  RT_ADD_VLIST(vhead,
194  vu->a.plane_p->N,
196  }
197  RT_ADD_VLIST(vhead, vg->coord, BN_VLIST_POLY_MOVE);
198  } else {
199  /* move */
200  RT_ADD_VLIST(vhead, vg->coord, BN_VLIST_LINE_MOVE);
201  }
202  isfirst = 0;
203  first_vg = vg;
204  first_vu = vu;
205  } else {
206  if (poly_markers & NMG_VLIST_STYLE_POLYGON) {
207  if (poly_markers & NMG_VLIST_STYLE_USE_VU_NORMALS
208  && vu->a.magic_p) {
209  RT_ADD_VLIST(vhead,
210  vu->a.plane_p->N,
212  }
213  RT_ADD_VLIST(vhead, vg->coord, BN_VLIST_POLY_DRAW);
214  } else {
215  /* Draw */
216  RT_ADD_VLIST(vhead, vg->coord, BN_VLIST_LINE_DRAW);
217  }
218  }
219 
220  if (!eu->g.magic_p)
221  continue;
222 
223  /* If cnurb edgeuse, draw points interior to the curve here */
224  if (*eu->g.magic_p != NMG_EDGE_G_CNURB_MAGIC) continue;
225 
226  /* XXX only use poly markers when face is planar, not snurb */
227  nmg_cnurb_to_vlist(vhead, eu, 10,
228  (poly_markers & NMG_VLIST_STYLE_POLYGON) ?
230  }
231 
232  /* Draw back to the first vertex used */
233  if (!isfirst && first_vg) {
234  if (poly_markers & NMG_VLIST_STYLE_POLYGON) {
235  /* Draw, end polygon */
236  if (poly_markers & NMG_VLIST_STYLE_USE_VU_NORMALS
237  && first_vu->a.magic_p) {
238  RT_ADD_VLIST(vhead,
239  first_vu->a.plane_p->N,
241  }
242  RT_ADD_VLIST(vhead, first_vg->coord, BN_VLIST_POLY_END);
243  } else {
244  /* Draw */
245  RT_ADD_VLIST(vhead, first_vg->coord, BN_VLIST_LINE_DRAW);
246  }
247  }
248  if ((poly_markers & NMG_VLIST_STYLE_VISUALIZE_NORMALS) && npoints > 2) {
249  /* Draw surface normal as a little vector */
250  double f;
251  vect_t tocent;
252  point_t tip;
253  struct faceuse *fu;
254  struct face *fp;
255 
256  if (*lu->up.magic_p == NMG_FACEUSE_MAGIC) {
257  fu = lu->up.fu_p;
258  NMG_CK_FACEUSE(fu);
259 
260  fp = fu->f_p;
261  } else
262  fp = (struct face *)NULL;
263 
264  f = 1.0 / npoints;
265  VSCALE(centroid, centroid, f);
266  VSUB2(tocent, first_vg->coord, centroid);
267  f = MAGNITUDE(tocent) * 0.5;
268  if (fp) {
269  if (*fp->g.magic_p != NMG_FACE_G_SNURB_MAGIC) {
270  /* snurb normals are plotted in nmg_snurb_fu_to_vlist() */
271  RT_ADD_VLIST(vhead, centroid, BN_VLIST_LINE_MOVE);
272  VJOIN1(tip, centroid, f, normal);
273  RT_ADD_VLIST(vhead, tip, BN_VLIST_LINE_DRAW);
274  }
275  }
276 
277  /* For any vertexuse attributes with normals, draw them too */
278  for (BU_LIST_FOR(eu, edgeuse, &lu->down_hd)) {
279  struct vertexuse_a_plane *vua;
280  /* Consider this edge */
281  vu = eu->vu_p;
282  if (!vu->a.magic_p || *vu->a.magic_p != NMG_VERTEXUSE_A_PLANE_MAGIC) continue;
283  vua = vu->a.plane_p;
284  v = vu->v_p;
285  vg = v->vg_p;
286  if (!vg) continue;
287  NMG_CK_VERTEX_G(vg);
288  RT_ADD_VLIST(vhead, vg->coord, BN_VLIST_LINE_MOVE);
289  VJOIN1(tip, vg->coord, f, vua->N);
290  RT_ADD_VLIST(vhead, tip, BN_VLIST_LINE_DRAW);
291  }
292  }
293 }
294 
295 
296 void
297 nmg_snurb_fu_to_vlist(struct bu_list *vhead, const struct faceuse *fu, int poly_markers)
298 {
299  struct face_g_snurb *fg;
300 
301  BU_CK_LIST_HEAD(vhead);
302 
303  NMG_CK_FACEUSE(fu);
304  NMG_CK_FACE(fu->f_p);
305  fg = fu->f_p->g.snurb_p;
306  NMG_CK_FACE_G_SNURB(fg);
307 
308  /* XXX For now, draw the whole surface, not just the interior */
309  nmg_snurb_to_vlist(vhead, fg, 10);
310 
311  if (poly_markers & NMG_VLIST_STYLE_VISUALIZE_NORMALS) {
312  fastf_t f;
313  point_t uv_centroid;
314  point_t mid_srf;
315  point_t corner;
316  vect_t fu_norm;
317  vect_t tocent;
318  point_t tip;
319 
320  uv_centroid[0] = (fg->u.knots[fg->u.k_size-1] + fg->u.knots[0])/2.0;
321  uv_centroid[1] = (fg->v.knots[fg->v.k_size-1] + fg->v.knots[0])/2.0;
322  uv_centroid[2] = 1.0;
323 
324  nmg_snurb_fu_get_norm(fu, uv_centroid[0], uv_centroid[1], fu_norm);
325  nmg_snurb_fu_eval(fu, uv_centroid[0], uv_centroid[1], mid_srf);
326 
327  nmg_snurb_fu_eval(fu, fg->u.knots[0], fg->v.knots[0], corner);
328  VSUB2(tocent, corner, mid_srf);
329  f = MAGNITUDE(tocent) * 0.5;
330 
331  RT_ADD_VLIST(vhead, mid_srf, BN_VLIST_LINE_MOVE);
332  VJOIN1(tip, mid_srf, f, fu_norm);
333  RT_ADD_VLIST(vhead, tip, BN_VLIST_LINE_DRAW);
334  }
335 }
336 
337 
338 /**
339  * Plot the entire contents of a shell.
340  *
341  * poly_markers =
342  * 0 for vectors
343  * 1 for polygons
344  * 2 for polygons and surface normals drawn with vectors
345  */
346 void
347 nmg_s_to_vlist(struct bu_list *vhead, const struct shell *s, int poly_markers)
348 {
349  struct faceuse *fu;
350  struct face_g_plane *fg;
351  register struct loopuse *lu;
352  vect_t normal;
353 
354  BU_CK_LIST_HEAD(vhead);
355  NMG_CK_SHELL(s);
356 
357  /* faces */
358  for (BU_LIST_FOR(fu, faceuse, &s->fu_hd)) {
359  vect_t n;
360 
361  /* Consider this face */
362  NMG_CK_FACEUSE(fu);
363  if (fu->orientation != OT_SAME) continue;
364  NMG_CK_FACE(fu->f_p);
365 
366  if (fu->f_p->g.magic_p && *fu->f_p->g.magic_p == NMG_FACE_G_SNURB_MAGIC) {
367 
368  if (!(poly_markers & NMG_VLIST_STYLE_NO_SURFACES))
369  nmg_snurb_fu_to_vlist(vhead, fu, poly_markers);
370 
371  VSET(n, 1, 0, 0); /* sanity */
372  for (BU_LIST_FOR(lu, loopuse, &fu->lu_hd)) {
373  nmg_lu_to_vlist(vhead, lu, poly_markers, n);
374  }
375  continue;
376  }
377 
378  /* Handle planar faces directly */
379  fg = fu->f_p->g.plane_p;
380  NMG_CK_FACE_G_PLANE(fg);
381  NMG_GET_FU_NORMAL(n, fu);
382  for (BU_LIST_FOR(lu, loopuse, &fu->lu_hd)) {
383  nmg_lu_to_vlist(vhead, lu, poly_markers, n);
384  }
385  }
386 
387  /* wire loops. poly_markers=0 so wires are always drawn as vectors */
388  VSETALL(normal, 0);
389  for (BU_LIST_FOR(lu, loopuse, &s->lu_hd)) {
390  nmg_lu_to_vlist(vhead, lu, 0, normal);
391  }
392 
393  /* wire edges */
394  nmg_eu_to_vlist(vhead, &s->eu_hd);
395 
396  /* single vertices */
397  if (s->vu_p) {
398  nmg_vu_to_vlist(vhead, s->vu_p);
399  }
400 }
401 
402 
403 void
404 nmg_r_to_vlist(struct bu_list *vhead, const struct nmgregion *r, int poly_markers)
405 {
406  register struct shell *s;
407 
408  BU_CK_LIST_HEAD(vhead);
409  NMG_CK_REGION(r);
410  for (BU_LIST_FOR(s, shell, &r->s_hd)) {
411  nmg_s_to_vlist(vhead, s, poly_markers);
412  }
413 }
414 
415 
416 void
417 nmg_m_to_vlist(struct bu_list *vhead, struct model *m, int poly_markers)
418 {
419  register struct nmgregion *r;
420 
421  BU_CK_LIST_HEAD(vhead);
422  NMG_CK_MODEL(m);
423  for (BU_LIST_FOR(r, nmgregion, &m->r_hd)) {
424  NMG_CK_REGION(r);
425  nmg_r_to_vlist(vhead, r, poly_markers);
426  }
427 }
428 
429 
430 /************************************************************************
431  * *
432  * Routines to lay out the fancy edgeuse drawings *
433  * *
434  ************************************************************************/
435 
436 #define LEE_DIVIDE_TOL (1.0e-5) /* sloppy tolerance */
437 
438 
439 /**
440  * Given an edgeuse, find an offset for its vertexuse which will place
441  * it "above" and "inside" the area of the face.
442  *
443  * The point will be offset inwards along the edge slightly, to avoid
444  * obscuring the vertex, and will be offset off the face (in the
445  * direction of the face normal) slightly, to avoid obscuring the edge
446  * itself.
447  */
448 void
449 nmg_offset_eu_vert(fastf_t *base, const struct edgeuse *eu, const fastf_t *face_normal, int tip)
450 {
451  struct edgeuse *prev_eu;
452  const struct edgeuse *this_eu;
453  vect_t prev_vec; /* from cur_pt to prev_pt */
454  vect_t eu_vec; /* from cur_pt to next_pt */
455  vect_t prev_left;
456  vect_t eu_left;
457  vect_t delta_vec; /* offset vector from vertex */
458  struct vertex_g *this_vg, *mate_vg, *prev_vg;
459 
460  memset((char *)delta_vec, 0, sizeof(vect_t));
461  prev_eu = BU_LIST_PPREV_CIRC(edgeuse, eu);
462  this_eu = eu;
463 
464  NMG_CK_EDGEUSE(this_eu);
465  NMG_CK_VERTEXUSE(this_eu->vu_p);
466  NMG_CK_VERTEX(this_eu->vu_p->v_p);
467  this_vg = this_eu->vu_p->v_p->vg_p;
468  NMG_CK_VERTEX_G(this_vg);
469 
470  NMG_CK_EDGEUSE(this_eu->eumate_p);
471  NMG_CK_VERTEXUSE(this_eu->eumate_p->vu_p);
472  NMG_CK_VERTEX(this_eu->eumate_p->vu_p->v_p);
473  mate_vg = this_eu->eumate_p->vu_p->v_p->vg_p;
474  NMG_CK_VERTEX_G(mate_vg);
475 
476  NMG_CK_EDGEUSE(prev_eu);
477  NMG_CK_VERTEXUSE(prev_eu->vu_p);
478  NMG_CK_VERTEX(prev_eu->vu_p->v_p);
479  prev_vg = prev_eu->vu_p->v_p->vg_p;
480  NMG_CK_VERTEX_G(prev_vg);
481 
482  /* get "left" vector for edgeuse */
483  VSUB2(eu_vec, mate_vg->coord, this_vg->coord);
484  VUNITIZE(eu_vec);
485  VCROSS(eu_left, face_normal, eu_vec);
486 
487 
488  /* get "left" vector for previous edgeuse */
489  VSUB2(prev_vec, this_vg->coord, prev_vg->coord);
490  VUNITIZE(prev_vec);
491  VCROSS(prev_left, face_normal, prev_vec);
492 
493  /* get "delta" vector to apply to vertex */
494  VADD2(delta_vec, prev_left, eu_left);
495 
496  if (MAGSQ(delta_vec) > VDIVIDE_TOL) {
497  VUNITIZE(delta_vec);
498  VJOIN2(base, this_vg->coord,
499  (nmg_eue_dist*1.3), delta_vec,
500  (nmg_eue_dist*0.8), face_normal);
501 
502  } else if (tip) {
503  VJOIN2(base, this_vg->coord,
504  (nmg_eue_dist*1.3), prev_left,
505  (nmg_eue_dist*0.8), face_normal);
506  } else {
507  VJOIN2(base, this_vg->coord,
508  (nmg_eue_dist*1.3), eu_left,
509  (nmg_eue_dist*0.8), face_normal);
510  }
511 }
512 
513 
514 /**
515  * Get the two (offset and shrunken) endpoints that represent an
516  * edgeuse. Return the base point, and a point 60% along the way
517  * towards the other end.
518  */
519 static void nmg_eu_coords(const struct edgeuse *eu, fastf_t *base, fastf_t *tip60)
520 {
521  point_t tip = VINIT_ZERO;
522 
523  NMG_CK_EDGEUSE(eu);
524 
525  if (*eu->up.magic_p == NMG_SHELL_MAGIC ||
526  (*eu->up.magic_p == NMG_LOOPUSE_MAGIC &&
527  *eu->up.lu_p->up.magic_p == NMG_SHELL_MAGIC)) {
528  /* Wire edge, or edge in wire loop */
529  VMOVE(base, eu->vu_p->v_p->vg_p->coord);
530  NMG_CK_EDGEUSE(eu->eumate_p);
531  VMOVE(tip, eu->eumate_p->vu_p->v_p->vg_p->coord);
532  } else if (*eu->up.magic_p == NMG_LOOPUSE_MAGIC &&
533  *eu->up.lu_p->up.magic_p == NMG_FACEUSE_MAGIC) {
534  /* Loop in face */
535  struct faceuse *fu;
536  vect_t face_normal;
537 
538  fu = eu->up.lu_p->up.fu_p;
539  NMG_GET_FU_NORMAL(face_normal, fu);
540 
541 
542  nmg_offset_eu_vert(base, eu, face_normal, 0);
543  nmg_offset_eu_vert(tip, BU_LIST_PNEXT_CIRC(edgeuse, eu),
544  face_normal, 1);
545 
546  } else
547  bu_bomb("nmg_eu_coords: bad edgeuse up. What's going on?\n");
548 
549  VBLEND2(tip60, 0.4, base, 0.6, tip);
550 }
551 
552 
553 /**
554  * Find location for 80% tip on edgeuse's radial edgeuse.
555  */
556 static void nmg_eu_radial(const struct edgeuse *eu, fastf_t *tip)
557 {
558  point_t b2 = VINIT_ZERO;
559  point_t t2 = VINIT_ZERO;
560 
561  NMG_CK_EDGEUSE(eu->radial_p);
562  NMG_CK_VERTEXUSE(eu->radial_p->vu_p);
563  NMG_CK_VERTEX(eu->radial_p->vu_p->v_p);
564  NMG_CK_VERTEX_G(eu->radial_p->vu_p->v_p->vg_p);
565 
566  nmg_eu_coords(eu->radial_p, b2, t2);
567 
568  /* find point 80% along other eu where radial pointer should touch */
569  VCOMB2(tip, 0.8, t2, 0.2, b2);
570 }
571 
572 
573 /**
574  * Return the base of the next edgeuse
575  */
576 static void nmg_eu_next_base(const struct edgeuse *eu, fastf_t *next_base)
577 {
578  point_t t2;
579  register struct edgeuse *nexteu;
580 
581  NMG_CK_EDGEUSE(eu);
582  nexteu = BU_LIST_PNEXT_CIRC(edgeuse, eu);
583  NMG_CK_EDGEUSE(nexteu);
584  NMG_CK_VERTEXUSE(nexteu->vu_p);
585  NMG_CK_VERTEX(nexteu->vu_p->v_p);
586  NMG_CK_VERTEX_G(nexteu->vu_p->v_p->vg_p);
587 
588  nmg_eu_coords(nexteu, next_base, t2);
589 }
590 
591 
592 /************************************************************************
593  * *
594  * NMG to UNIX-Plot routines, for visualization *
595  * XXX These should get replaced with calls to the vlblock routines *
596  * *
597  ************************************************************************/
598 
599 void
600 nmg_pl_v(FILE *fp, const struct vertex *v, long *b)
601 {
602  pointp_t p;
603  static char label[128];
604 
605  NMG_INDEX_RETURN_IF_SET_ELSE_SET(b, v->index);
606 
607  NMG_CK_VERTEX(v);
608  NMG_CK_VERTEX_G(v->vg_p);
609  p = v->vg_p->coord;
610 
611  pl_color(fp, 255, 255, 255);
612  if (RTG.NMG_debug & DEBUG_LABEL_PTS) {
613  (void)sprintf(label, "%g %g %g", p[0], p[1], p[2]);
614  pdv_3move(fp, p);
615  pl_label(fp, label);
616  }
617  pdv_3point(fp, p);
618 }
619 
620 
621 void
622 nmg_pl_e(FILE *fp, const struct edge *e, long *b, int red, int green, int blue)
623 {
624  pointp_t p0, p1;
625  point_t end0, end1;
626  vect_t v;
627 
628  NMG_INDEX_RETURN_IF_SET_ELSE_SET(b, e->index);
629 
630  NMG_CK_EDGEUSE(e->eu_p);
631  NMG_CK_VERTEXUSE(e->eu_p->vu_p);
632  NMG_CK_VERTEX(e->eu_p->vu_p->v_p);
633  NMG_CK_VERTEX_G(e->eu_p->vu_p->v_p->vg_p);
634  p0 = e->eu_p->vu_p->v_p->vg_p->coord;
635 
636  NMG_CK_VERTEXUSE(e->eu_p->eumate_p->vu_p);
637  NMG_CK_VERTEX(e->eu_p->eumate_p->vu_p->v_p);
638  NMG_CK_VERTEX_G(e->eu_p->eumate_p->vu_p->v_p->vg_p);
639  p1 = e->eu_p->eumate_p->vu_p->v_p->vg_p->coord;
640 
641  /* leave a little room between the edge endpoints and the vertex
642  * compute endpoints by forming a vector between verts, scale
643  * vector and modify points
644  */
645  VSUB2SCALE(v, p1, p0, 0.95);
646  VADD2(end0, p0, v);
647  VSUB2(end1, p1, v);
648 
649  pl_color(fp, red, green, blue);
650  pdv_3line(fp, end0, end1);
651 
652  nmg_pl_v(fp, e->eu_p->vu_p->v_p, b);
653  nmg_pl_v(fp, e->eu_p->eumate_p->vu_p->v_p, b);
654 }
655 
656 
657 void
658 nmg_pl_eu(FILE *fp, const struct edgeuse *eu, long *b, int red, int green, int blue)
659 {
660  point_t base, tip;
661  point_t radial_tip;
662  point_t next_base;
663 
664  NMG_CK_EDGEUSE(eu);
665  NMG_CK_EDGE(eu->e_p);
666  NMG_CK_VERTEXUSE(eu->vu_p);
667  NMG_CK_VERTEX(eu->vu_p->v_p);
668  NMG_CK_VERTEX_G(eu->vu_p->v_p->vg_p);
669 
670  NMG_CK_VERTEXUSE(eu->eumate_p->vu_p);
671  NMG_CK_VERTEX(eu->eumate_p->vu_p->v_p);
672  NMG_CK_VERTEX_G(eu->eumate_p->vu_p->v_p->vg_p);
673 
674  NMG_INDEX_RETURN_IF_SET_ELSE_SET(b, eu->index);
675 
676  nmg_pl_e(fp, eu->e_p, b, red, green, blue);
677 
678  if (*eu->up.magic_p == NMG_LOOPUSE_MAGIC &&
679  *eu->up.lu_p->up.magic_p == NMG_FACEUSE_MAGIC) {
680 
681  nmg_eu_coords(eu, base, tip);
682  if (eu->up.lu_p->up.fu_p->orientation == OT_SAME)
683  red += 50;
684  else if (eu->up.lu_p->up.fu_p->orientation == OT_OPPOSITE)
685  red -= 50;
686  else
687  red = green = blue = 255;
688 
689  pl_color(fp, red, green, blue);
690  pdv_3line(fp, base, tip);
691 
692  nmg_eu_radial(eu, radial_tip);
693  pl_color(fp, red, green-20, blue);
694  pdv_3line(fp, tip, radial_tip);
695 
696  pl_color(fp, 0, 100, 0);
697  nmg_eu_next_base(eu, next_base);
698  pdv_3line(fp, tip, next_base);
699 
700 /*** presently unused ***
701  nmg_eu_last(eu, last_tip);
702  pl_color(fp, 0, 200, 0);
703  pdv_3line(fp, base, last_tip);
704 ****/
705  }
706 }
707 
708 
709 void
710 nmg_pl_lu(FILE *fp, const struct loopuse *lu, long *b, int red, int green, int blue)
711 {
712  struct bn_vlblock *vbp;
713 
714  vbp = rt_vlblock_init();
715  nmg_vlblock_lu(vbp, lu, b, red, green, blue, 0);
716  rt_plot_vlblock(fp, vbp);
717  rt_vlblock_free(vbp);
718 }
719 
720 
721 void
722 nmg_pl_fu(FILE *fp, const struct faceuse *fu, long *b, int red, int green, int blue)
723 {
724  struct loopuse *lu;
725  struct bn_vlblock *vbp;
726 
727  NMG_CK_FACEUSE(fu);
728  NMG_INDEX_RETURN_IF_SET_ELSE_SET(b, fu->index);
729 
730  vbp = rt_vlblock_init();
731 
732  for (BU_LIST_FOR(lu, loopuse, &fu->lu_hd)) {
733  nmg_vlblock_lu(vbp, lu, b, red, green, blue, 1);
734  }
735 
736  rt_plot_vlblock(fp, vbp);
737  rt_vlblock_free(vbp);
738 }
739 
740 
741 /**
742  * Note that "b" should probably be defined a level higher, to reduce
743  * malloc/free calls when plotting multiple shells.
744  */
745 void
746 nmg_pl_s(FILE *fp, const struct shell *s)
747 {
748  struct bn_vlblock *vbp;
749 
750  vbp = rt_vlblock_init();
751  nmg_vlblock_s(vbp, s, 0);
752  rt_plot_vlblock(fp, vbp);
753  rt_vlblock_free(vbp);
754 }
755 
756 
757 void
758 nmg_pl_shell(FILE *fp, const struct shell *s, int fancy)
759 {
760  struct bn_vlblock *vbp;
761 
762  vbp = rt_vlblock_init();
763  nmg_vlblock_s(vbp, s, fancy);
764  rt_plot_vlblock(fp, vbp);
765  rt_vlblock_free(vbp);
766 }
767 
768 
769 void
770 nmg_pl_r(FILE *fp, const struct nmgregion *r)
771 {
772  struct bn_vlblock *vbp;
773 
774  vbp = rt_vlblock_init();
775  nmg_vlblock_r(vbp, r, 0);
776  rt_plot_vlblock(fp, vbp);
777  rt_vlblock_free(vbp);
778 }
779 
780 
781 void
782 nmg_pl_m(FILE *fp, const struct model *m)
783 {
784  struct bn_vlblock *vbp;
785 
786  vbp = rt_vlblock_init();
787  nmg_vlblock_m(vbp, m, 0);
788  rt_plot_vlblock(fp, vbp);
789  rt_vlblock_free(vbp);
790 }
791 
792 
793 /************************************************************************
794  * *
795  * Visualization of fancy edgeuses into VLBLOCKs *
796  * *
797  * This is the preferred method of obtaining fancy NMG displays. *
798  * *
799  ************************************************************************/
800 
801 void
802 nmg_vlblock_v(struct bn_vlblock *vbp, const struct vertex *v, long *tab)
803 {
804  pointp_t p;
805  struct bu_list *vh;
806 
807  BN_CK_VLBLOCK(vbp);
808  NMG_CK_VERTEX(v);
809  NMG_INDEX_RETURN_IF_SET_ELSE_SET(tab, v->index);
810 
811  NMG_CK_VERTEX_G(v->vg_p);
812  p = v->vg_p->coord;
813 
814  vh = rt_vlblock_find(vbp, 255, 255, 255);
817 }
818 
819 
820 void
821 nmg_vlblock_e(struct bn_vlblock *vbp, const struct edge *e, long *tab, int red, int green, int blue)
822 {
823  pointp_t p0, p1;
824  point_t end0, end1;
825  vect_t v;
826  struct bu_list *vh;
827 
828  BN_CK_VLBLOCK(vbp);
829  NMG_CK_EDGE(e);
830  NMG_INDEX_RETURN_IF_SET_ELSE_SET(tab, e->index);
831 
832  NMG_CK_EDGEUSE(e->eu_p);
833  NMG_CK_VERTEXUSE(e->eu_p->vu_p);
834  NMG_CK_VERTEX(e->eu_p->vu_p->v_p);
835  NMG_CK_VERTEX_G(e->eu_p->vu_p->v_p->vg_p);
836  p0 = e->eu_p->vu_p->v_p->vg_p->coord;
837 
838  NMG_CK_VERTEXUSE(e->eu_p->eumate_p->vu_p);
839  NMG_CK_VERTEX(e->eu_p->eumate_p->vu_p->v_p);
840  NMG_CK_VERTEX_G(e->eu_p->eumate_p->vu_p->v_p->vg_p);
841  p1 = e->eu_p->eumate_p->vu_p->v_p->vg_p->coord;
842 
843  /* leave a little room between the edge endpoints and the vertex
844  * compute endpoints by forming a vector between verts, scale vector
845  * and modify points
846  */
847  VSUB2SCALE(v, p1, p0, 0.90);
848  VADD2(end0, p0, v);
849  VSUB2(end1, p1, v);
850 
851  vh = rt_vlblock_find(vbp, red, green, blue);
852  RT_ADD_VLIST(vh, end0, BN_VLIST_LINE_MOVE);
853  RT_ADD_VLIST(vh, end1, BN_VLIST_LINE_DRAW);
854 
855  nmg_vlblock_v(vbp, e->eu_p->vu_p->v_p, tab);
856  nmg_vlblock_v(vbp, e->eu_p->eumate_p->vu_p->v_p, tab);
857 }
858 
859 
860 void
861 nmg_vlblock_eu(struct bn_vlblock *vbp, const struct edgeuse *eu, long *tab, int red, int green, int blue, int fancy)
862 {
863  point_t base = VINIT_ZERO;
864  point_t next_base = VINIT_ZERO;
865  point_t radial_tip = VINIT_ZERO;
866  point_t tip = VINIT_ZERO;
867  struct bu_list *vh = NULL;
868 
869  BN_CK_VLBLOCK(vbp);
870  NMG_CK_EDGEUSE(eu);
871  NMG_INDEX_RETURN_IF_SET_ELSE_SET(tab, eu->index);
872 
873  NMG_CK_EDGE(eu->e_p);
874  NMG_CK_VERTEXUSE(eu->vu_p);
875  NMG_CK_VERTEX(eu->vu_p->v_p);
876  NMG_CK_VERTEX_G(eu->vu_p->v_p->vg_p);
877 
878  NMG_CK_VERTEXUSE(eu->eumate_p->vu_p);
879  NMG_CK_VERTEX(eu->eumate_p->vu_p->v_p);
880  NMG_CK_VERTEX_G(eu->eumate_p->vu_p->v_p->vg_p);
881 
882  nmg_vlblock_e(vbp, eu->e_p, tab, red, green, blue);
883 
884  if (!fancy) return;
885 
886  if (*eu->up.magic_p == NMG_LOOPUSE_MAGIC &&
887  *eu->up.lu_p->up.magic_p == NMG_FACEUSE_MAGIC) {
888 
889  /* if "fancy" doesn't specify plotting edgeuses of this
890  * particular face orientation, return
891  */
892  if ((eu->up.lu_p->up.fu_p->orientation == OT_SAME &&
893  (fancy & 1) == 0) ||
894  (eu->up.lu_p->up.fu_p->orientation == OT_OPPOSITE &&
895  (fancy & 2) == 0))
896  return;
897 
898  nmg_eu_coords(eu, base, tip);
899  /* draw edgeuses of an OT_SAME faceuse in bright green, and
900  * edgeuses of an OT_OPPOSITE faceuse in cyan. WIRE/UNSPEC
901  * edgeuses are drawn white.
902  */
903  if (eu->up.lu_p->up.fu_p->orientation == OT_SAME) {
904  if (eu->up.lu_p->orientation == OT_SAME) {
905  /* green */
906  red = 75;
907  green = 250;
908  blue = 75;
909  } else if (eu->up.lu_p->orientation == OT_OPPOSITE) {
910  /* yellow */
911  red = 250;
912  green = 250;
913  blue = 75;
914  } else {
915  red = 250;
916  green = 50;
917  blue = 250;
918  }
919  } else if (eu->up.lu_p->up.fu_p->orientation == OT_OPPOSITE) {
920  if (eu->up.lu_p->orientation == OT_SAME) {
921  /* blue */
922  red = 100;
923  green = 100;
924  blue = 250;
925  } else if (eu->up.lu_p->orientation == OT_OPPOSITE) {
926  /* cyan */
927  red = 200;
928  green = 100;
929  blue = 250;
930  } else {
931  /* dark magenta */
932  red = 125;
933  green = 0;
934  blue = 125;
935  }
936  } else
937  red = green = blue = 255;
938 
939  /* draw the portion from the vertexuse to just beyond the
940  * midway point to represent the edgeuse
941  */
942  vh = rt_vlblock_find(vbp, red, green, blue);
943  RT_ADD_VLIST(vh, base, BN_VLIST_LINE_MOVE);
945 
946  /* draw a line from the tip of the edgeuse part to a point
947  * behind the tip of the radial edgeuse. This provides 2
948  * visual cues. First it allows us to identify the radial
949  * edgeuse, and second, it makes a "half arrowhead" on the
950  * edgeuse, making it easier to recognize the direction of the
951  * edgeuse
952  */
953  nmg_eu_radial(eu, radial_tip);
954  vh = rt_vlblock_find(vbp, red, green-20, blue);
956  RT_ADD_VLIST(vh, radial_tip, BN_VLIST_LINE_DRAW);
957 
958  /* we draw a line from the tip of the edgeuse line to the
959  * vertexuse/start of the next edgeuse in the loop. This
960  * helps us to visually trace the loop from edgeuse to
961  * edgeuse. The color of this part encodes the loopuse
962  * orientation.
963  */
964  nmg_eu_next_base(eu, next_base);
965  red *= 0.5;
966  green *= 0.5;
967  blue *= 0.5;
968  vh = rt_vlblock_find(vbp, red, green, blue);
970  RT_ADD_VLIST(vh, next_base, BN_VLIST_LINE_DRAW);
971  }
972 }
973 
974 
975 /**
976  * Draw the left vector for this edgeuse.
977  * At the tip, write the angle around the edgeuse, in degrees.
978  *
979  * Color is determined by caller.
980  */
981 void
982 nmg_vlblock_euleft(struct bu_list *vh, const struct edgeuse *eu, const fastf_t *center, const fastf_t *mat, const fastf_t *xvec, const fastf_t *yvec, double len, const struct bn_tol *tol)
983 {
984  vect_t left;
985  point_t tip;
986  fastf_t fan_len;
987  fastf_t char_scale;
988  double ang;
989  char str[128];
990 
991  NMG_CK_EDGEUSE(eu);
992  BN_CK_TOL(tol);
993 
994  if (nmg_find_eu_leftvec(left, eu) < 0) return;
995 
996  /* fan_len is based on length of eu */
997  fan_len = len * 0.2;
998  VJOIN1(tip, center, fan_len, left);
999 
1000  RT_ADD_VLIST(vh, center, BN_VLIST_LINE_MOVE);
1001  RT_ADD_VLIST(vh, tip, BN_VLIST_LINE_DRAW);
1002 
1003  ang = bn_angle_measure(left, xvec, yvec) * RAD2DEG;
1004  sprintf(str, "%g", ang);
1005 
1006  /* char_scale is based on length of eu */
1007  char_scale = len * 0.05;
1008  bn_vlist_3string(vh, &RTG.rtg_vlfree, str, tip, mat, char_scale);
1009 }
1010 
1011 
1012 /**
1013  * Given an edgeuse, plot all the edgeuses around the common edge. A
1014  * graphical parallel to nmg_pr_fu_around_eu_vecs().
1015  *
1016  * If the "fancy" flag is set, draw an angle fan around the edge
1017  * midpoint, using the same angular reference as
1018  * nmg_pr_fu_around_eu_vecs(), so that the printed output can be
1019  * cross-referenced to this display.
1020  */
1021 void
1022 nmg_vlblock_around_eu(struct bn_vlblock *vbp, const struct edgeuse *arg_eu, long *tab, int fancy, const struct bn_tol *tol)
1023 {
1024  const struct edgeuse *orig_eu;
1025  register const struct edgeuse *eu;
1026  vect_t xvec, yvec, zvec;
1027  point_t center = VINIT_ZERO;
1028  mat_t mat;
1029  struct bu_list *vh;
1030  fastf_t len;
1031 
1032  BN_CK_VLBLOCK(vbp);
1033  NMG_CK_EDGEUSE(arg_eu);
1034  BN_CK_TOL(tol);
1035 
1036  if (fancy) {
1037  VSUB2(xvec, arg_eu->eumate_p->vu_p->v_p->vg_p->coord,
1038  arg_eu->vu_p->v_p->vg_p->coord);
1039  len = MAGNITUDE(xvec);
1040 
1041  /* Erect coordinate system around eu */
1042  nmg_eu_2vecs_perp(xvec, yvec, zvec, arg_eu, tol);
1043 
1044  /* Construct matrix to rotate characters from 2D drawing space
1045  * into model coordinates, oriented in plane perpendicular to
1046  * eu.
1047  */
1048  MAT_ZERO(mat);
1049  mat[0] = xvec[X];
1050  mat[4] = xvec[Y];
1051  mat[8] = xvec[Z];
1052 
1053  mat[1] = yvec[X];
1054  mat[5] = yvec[Y];
1055  mat[9] = yvec[Z];
1056 
1057  mat[2] = zvec[X];
1058  mat[6] = zvec[Y];
1059  mat[10] = zvec[Z];
1060  mat[15] = 1;
1061 
1062  VADD2SCALE(center, arg_eu->vu_p->v_p->vg_p->coord,
1063  arg_eu->eumate_p->vu_p->v_p->vg_p->coord, 0.5);
1064 
1065  /* Yellow, for now */
1066  vh = rt_vlblock_find(vbp, 255, 200, 0);
1067  } else {
1068  vh = (struct bu_list *)NULL;
1069  len = 1;
1070  }
1071 
1072  orig_eu = arg_eu->eumate_p;
1073 
1074  eu = orig_eu;
1075  do {
1076  if (fancy) nmg_vlblock_euleft(vh, eu, center, mat, xvec, yvec, len, tol);
1077 
1078  nmg_vlblock_eu(vbp, eu, tab, 80, 100, 170, 3);
1079  eu = eu->eumate_p;
1080 
1081  nmg_vlblock_eu(vbp, eu, tab, 80, 100, 170, 3);
1082  eu = eu->radial_p;
1083  } while (eu != orig_eu);
1084 }
1085 
1086 
1087 void
1088 nmg_vlblock_lu(struct bn_vlblock *vbp, const struct loopuse *lu, long *tab, int red, int green, int blue, int fancy)
1089 {
1090  struct edgeuse *eu;
1091  uint32_t magic1;
1092  struct vertexuse *vu;
1093 
1094  BN_CK_VLBLOCK(vbp);
1095  NMG_CK_LOOPUSE(lu);
1096  NMG_INDEX_RETURN_IF_SET_ELSE_SET(tab, lu->index);
1097 
1098  magic1 = BU_LIST_FIRST_MAGIC(&lu->down_hd);
1099  if (magic1 == NMG_VERTEXUSE_MAGIC &&
1100  lu->orientation != OT_BOOLPLACE) {
1101  vu = BU_LIST_PNEXT(vertexuse, &lu->down_hd);
1102  NMG_CK_VERTEXUSE(vu);
1103  nmg_vlblock_v(vbp, vu->v_p, tab);
1104  } else if (magic1 == NMG_EDGEUSE_MAGIC) {
1105  for (BU_LIST_FOR(eu, edgeuse, &lu->down_hd)) {
1106  nmg_vlblock_eu(vbp, eu, tab, red, green, blue, fancy);
1107  }
1108  }
1109 }
1110 
1111 
1112 void
1113 nmg_vlblock_fu(struct bn_vlblock *vbp, const struct faceuse *fu, long *tab, int fancy)
1114 {
1115  struct loopuse *lu;
1116 
1117  BN_CK_VLBLOCK(vbp);
1118  NMG_CK_FACEUSE(fu);
1119  NMG_INDEX_RETURN_IF_SET_ELSE_SET(tab, fu->index);
1120 
1121  for (BU_LIST_FOR(lu, loopuse, &fu->lu_hd)) {
1122  /* Draw in pale blue / purple */
1123  if (fancy) {
1124  nmg_vlblock_lu(vbp, lu, tab, 80, 100, 170, fancy);
1125  } else {
1126  /* Non-fancy */
1127  nmg_vlblock_lu(vbp, lu, tab, 80, 100, 170, 0);
1128  }
1129  }
1130 }
1131 
1132 
1133 void
1134 nmg_vlblock_s(struct bn_vlblock *vbp, const struct shell *s, int fancy)
1135 {
1136  struct faceuse *fu;
1137  struct loopuse *lu;
1138  struct edgeuse *eu;
1139  struct model *m;
1140  long *tab;
1141 
1142  BN_CK_VLBLOCK(vbp);
1143  NMG_CK_SHELL(s);
1144  NMG_CK_REGION(s->r_p);
1145  m = s->r_p->m_p;
1146  NMG_CK_MODEL(m);
1147 
1148  /* get space for list of items processed */
1149  tab = (long *)bu_calloc(m->maxindex+1, sizeof(long), "nmg_vlblock_s tab[]");
1150 
1151  for (BU_LIST_FOR(fu, faceuse, &s->fu_hd)) {
1152  NMG_CK_FACEUSE(fu);
1153  nmg_vlblock_fu(vbp, fu, tab, fancy);
1154  }
1155 
1156  for (BU_LIST_FOR(lu, loopuse, &s->lu_hd)) {
1157  NMG_CK_LOOPUSE(lu);
1158  if (fancy) {
1159  nmg_vlblock_lu(vbp, lu, tab, 255, 0, 0, fancy);
1160  } else {
1161  /* non-fancy, wire loops in red */
1162  nmg_vlblock_lu(vbp, lu, tab, 200, 0, 0, 0);
1163  }
1164  }
1165 
1166  for (BU_LIST_FOR(eu, edgeuse, &s->eu_hd)) {
1167  NMG_CK_EDGEUSE(eu);
1168  NMG_CK_EDGE(eu->e_p);
1169 
1170  if (fancy) {
1171  nmg_vlblock_eu(vbp, eu, tab, 200, 200, 0, fancy);
1172  } else {
1173  /* non-fancy, wire edges in yellow */
1174  nmg_vlblock_eu(vbp, eu, tab, 200, 200, 0, 0);
1175  }
1176  }
1177  if (s->vu_p) {
1178  nmg_vlblock_v(vbp, s->vu_p->v_p, tab);
1179  }
1180 
1181  bu_free((char *)tab, "nmg_vlblock_s tab[]");
1182 }
1183 
1184 
1185 void
1186 nmg_vlblock_r(struct bn_vlblock *vbp, const struct nmgregion *r, int fancy)
1187 {
1188  struct shell *s;
1189 
1190  BN_CK_VLBLOCK(vbp);
1191  NMG_CK_REGION(r);
1192 
1193  for (BU_LIST_FOR(s, shell, &r->s_hd)) {
1194  nmg_vlblock_s(vbp, s, fancy);
1195  }
1196 }
1197 
1198 
1199 void
1200 nmg_vlblock_m(struct bn_vlblock *vbp, const struct model *m, int fancy)
1201 {
1202  struct nmgregion *r;
1203 
1204  BN_CK_VLBLOCK(vbp);
1205  NMG_CK_MODEL(m);
1206 
1207  for (BU_LIST_FOR(r, nmgregion, &m->r_hd)) {
1208  nmg_vlblock_r(vbp, r, fancy);
1209  }
1210 }
1211 
1212 
1213 /************************************************************************
1214  * *
1215  * Visualization helper routines *
1216  * *
1217  ************************************************************************/
1218 
1219 /**
1220  * If another use of this edge is in another shell, plot all the uses
1221  * around this edge.
1222  */
1223 void
1224 nmg_pl_edges_in_2_shells(struct bn_vlblock *vbp, long *b, const struct edgeuse *eu, int fancy, const struct bn_tol *tol)
1225 {
1226  const struct edgeuse *eur;
1227  const struct shell *s;
1228 
1229  BN_CK_TOL(tol);
1230  eur = eu;
1231  NMG_CK_EDGEUSE(eu);
1232  NMG_CK_LOOPUSE(eu->up.lu_p);
1233  NMG_CK_FACEUSE(eu->up.lu_p->up.fu_p);
1234  s = eu->up.lu_p->up.fu_p->s_p;
1235  NMG_CK_SHELL(s);
1236 
1237  do {
1238  NMG_CK_EDGEUSE(eur);
1239 
1240  if (*eur->up.magic_p == NMG_LOOPUSE_MAGIC &&
1241  *eur->up.lu_p->up.magic_p == NMG_FACEUSE_MAGIC &&
1242  eur->up.lu_p->up.fu_p->s_p != s) {
1243  nmg_vlblock_around_eu(vbp, eu, b, fancy, tol);
1244  break;
1245  }
1246 
1247  eur = eur->radial_p->eumate_p;
1248  } while (eur != eu);
1249 }
1250 
1251 
1252 /**
1253  * Called by nmg_bool.c
1254  */
1255 void
1256 nmg_pl_isect(const char *filename, const struct shell *s, const struct bn_tol *tol)
1257 {
1258  struct faceuse *fu;
1259  struct loopuse *lu;
1260  struct edgeuse *eu;
1261  long *b;
1262  FILE *fp;
1263  uint32_t magic1;
1264  struct bn_vlblock *vbp;
1265 
1266  NMG_CK_SHELL(s);
1267  BN_CK_TOL(tol);
1268 
1269  fp=fopen(filename, "wb");
1270  if (fp == (FILE *)NULL) {
1271  (void)perror(filename);
1272  bu_bomb("unable to open file for writing");
1273  }
1274 
1275  b = (long *)bu_calloc(s->r_p->m_p->maxindex+1, sizeof(long),
1276  "nmg_pl_isect flags[]");
1277 
1278  vbp = rt_vlblock_init();
1279 
1280  bu_log("overlay %s\n", filename);
1281  if (s->sa_p) {
1282  NMG_CK_SHELL_A(s->sa_p);
1283  }
1284 
1285  for (BU_LIST_FOR(fu, faceuse, &s->fu_hd)) {
1286  NMG_CK_FACEUSE(fu);
1287  for (BU_LIST_FOR(lu, loopuse, &fu->lu_hd)) {
1288  NMG_CK_LOOPUSE(lu);
1289  magic1 = BU_LIST_FIRST_MAGIC(&lu->down_hd);
1290  if (magic1 == NMG_EDGEUSE_MAGIC) {
1291  for (BU_LIST_FOR(eu, edgeuse, &lu->down_hd)) {
1292  NMG_CK_EDGEUSE(eu);
1293  nmg_pl_edges_in_2_shells(vbp, b, eu, 0, tol);
1294  }
1295  } else if (magic1 == NMG_VERTEXUSE_MAGIC) {
1296  ;
1297  } else {
1298  bu_bomb("nmg_pl_isect() bad loopuse down\n");
1299  }
1300  }
1301  }
1302 
1303  rt_plot_vlblock(fp, vbp);
1304  rt_vlblock_free(vbp);
1305 
1306  bu_free((char *)b, "nmg_pl_isect flags[]");
1307 
1308  (void)fclose(fp);
1309 }
1310 
1311 
1312 /**
1313  * Called from nmg_bool.c/nmg_face_combine()
1314  */
1315 void
1316 nmg_pl_comb_fu(int num1, int num2, const struct faceuse *fu1)
1317 {
1318  FILE *fp;
1319  char name[64];
1320  int do_plot = 0;
1321  int do_anim = 0;
1322  struct model *m;
1323  long *tab;
1324  struct bn_vlblock *vbp;
1325 
1326  if (RTG.NMG_debug & DEBUG_PLOTEM &&
1327  RTG.NMG_debug & DEBUG_FCUT) do_plot = 1;
1328  if (RTG.NMG_debug & DEBUG_PL_ANIM) do_anim = 1;
1329 
1330  if (!do_plot && !do_anim) return;
1331 
1332  m = nmg_find_model(&fu1->l.magic);
1333  NMG_CK_MODEL(m);
1334  /* get space for list of items processed */
1335  tab = (long *)bu_calloc(m->maxindex+1, sizeof(long),
1336  "nmg_pl_comb_fu tab[]");
1337 
1338  vbp = rt_vlblock_init();
1339 
1340  nmg_vlblock_fu(vbp, fu1, tab, 3);
1341 
1342  if (do_plot) {
1343  (void)sprintf(name, "comb%d.%d.plot3", num1, num2);
1344  fp = fopen(name, "wb");
1345  if (fp == (FILE *)NULL) {
1346  (void)perror(name);
1347  return;
1348  }
1349  bu_log("overlay %s\n", name);
1350 
1351  rt_plot_vlblock(fp, vbp);
1352 
1353  (void)fclose(fp);
1354  }
1355 
1356  if (do_anim) {
1358  /* need to cast nmg_vlblock_anim_upcall pointer for actual use as a function */
1359  void (*cfp)(struct bn_vlblock *, int, int);
1360  cfp = (void (*)(struct bn_vlblock *, int, int))nmg_vlblock_anim_upcall;
1361  cfp(vbp,
1362  (RTG.NMG_debug&DEBUG_PL_SLOW) ? US_DELAY : 0,
1363  0);
1364  } else {
1365  bu_log("null nmg_vlblock_anim_upcall, no animation\n");
1366  }
1367  }
1368  rt_vlblock_free(vbp);
1369  bu_free((char *)tab, "nmg_pl_comb_fu tab[]");
1370 }
1371 
1372 
1373 /**
1374  * Note that 'str' is expected to contain a %d to place the frame
1375  * number.
1376  *
1377  * Called from nmg_isect_2faces and other places.
1378  */
1379 void
1380 nmg_pl_2fu(const char *str, const struct faceuse *fu1, const struct faceuse *fu2, int show_mates)
1381 {
1382  FILE *fp;
1383  char name[32];
1384  struct model *m;
1385  long *tab;
1386  static int num = 1;
1387  struct bn_vlblock *vbp;
1388 
1389  if ((RTG.NMG_debug & (DEBUG_PLOTEM|DEBUG_PL_ANIM)) == 0) return;
1390 
1391  m = nmg_find_model(&fu1->l.magic);
1392  NMG_CK_MODEL(m);
1393  /* get space for list of items processed */
1394  tab = (long *)bu_calloc(m->maxindex+1, sizeof(long),
1395  "nmg_pl_comb_fu tab[]");
1396 
1397  /* Create the vlblock */
1398  vbp = rt_vlblock_init();
1399 
1400  nmg_vlblock_fu(vbp, fu1, tab, 3);
1401  if (show_mates)
1402  nmg_vlblock_fu(vbp, fu1->fumate_p, tab, 3);
1403 
1404  nmg_vlblock_fu(vbp, fu2, tab, 3);
1405  if (show_mates)
1406  nmg_vlblock_fu(vbp, fu2->fumate_p, tab, 3);
1407 
1408  if (RTG.NMG_debug & DEBUG_PLOTEM) {
1409  snprintf(name, 32, str, num++);
1410  bu_log("overlay %s\n", name);
1411  fp=fopen(name, "wb");
1412  if (fp == (FILE *)NULL) {
1413  perror(name);
1414  return;
1415  }
1416  rt_plot_vlblock(fp, vbp);
1417  (void)fclose(fp);
1418  }
1419 
1420  if (RTG.NMG_debug & DEBUG_PL_ANIM) {
1421  /* Cause animation of boolean operation as it proceeds! */
1423  /* need to cast nmg_vlblock_anim_upcall pointer for actual use as a function */
1424  void (*cfp)(struct bn_vlblock *, int, int);
1425  cfp = (void (*)(struct bn_vlblock *, int, int))nmg_vlblock_anim_upcall;
1426  cfp(vbp,
1427  (RTG.NMG_debug&DEBUG_PL_SLOW) ? US_DELAY : 0,
1428  0);
1429  }
1430  }
1431 
1432  rt_vlblock_free(vbp);
1433  bu_free((char *)tab, "nmg_pl_2fu tab[]");
1434 }
1435 
1436 
1437 /************************************************************************
1438  * *
1439  * Graphical display of classifier results *
1440  * *
1441  ************************************************************************/
1442 
1444 static char **global_classlist;
1445 static long *broken_tab;
1446 static int broken_tab_len;
1447 static int broken_color;
1448 static unsigned char broken_colors[][3] = {
1449  { 100, 100, 255 }, /* NMG_CLASS_AinB (bright blue) */
1450  { 255, 50, 50 }, /* NMG_CLASS_AonBshared (red) */
1451  { 255, 50, 255 }, /* NMG_CLASS_AonBanti (magenta) */
1452  { 50, 255, 50 }, /* NMG_CLASS_AoutB (bright green) */
1453  { 255, 255, 255 }, /* UNKNOWN (white) */
1454  { 255, 255, 125 } /* no classification list (cyan) */
1455 };
1456 #define PICK_BROKEN_COLOR(p) { \
1457  if (global_classlist == (char **)NULL) { \
1458  broken_color = 5; \
1459  } else if (NMG_INDEX_TEST(global_classlist[NMG_CLASS_AinB], (p))) \
1460  broken_color = NMG_CLASS_AinB; \
1461  else if (NMG_INDEX_TEST(global_classlist[NMG_CLASS_AonBshared], (p))) \
1462  broken_color = NMG_CLASS_AonBshared; \
1463  else if (NMG_INDEX_TEST(global_classlist[NMG_CLASS_AonBanti], (p))) \
1464  broken_color = NMG_CLASS_AonBanti; \
1465  else if (NMG_INDEX_TEST(global_classlist[NMG_CLASS_AoutB], (p))) \
1466  broken_color = NMG_CLASS_AoutB; \
1467  else \
1468  broken_color = 4;}
1469 
1470 HIDDEN void
1471 show_broken_vu(struct bn_vlblock *vbp, const struct vertexuse *vu)
1472 {
1473  pointp_t p;
1474  struct bu_list *vh;
1475  struct vertex *v;
1476  point_t pt;
1477 
1478  NMG_CK_VERTEXUSE(vu);
1479  v = vu->v_p;
1480  NMG_CK_VERTEX(v);
1481  NMG_CK_VERTEX_G(v->vg_p);
1482 
1483  NMG_INDEX_RETURN_IF_SET_ELSE_SET(broken_tab, v->index);
1484 
1485  NMG_CK_VERTEX_G(v->vg_p);
1486  p = v->vg_p->coord;
1487 
1488  PICK_BROKEN_COLOR(vu->v_p);
1489  if (broken_color == 4) {
1490  PICK_BROKEN_COLOR(vu);
1491  }
1492  vh = rt_vlblock_find(vbp,
1493  broken_colors[broken_color][0], broken_colors[broken_color][1], broken_colors[broken_color][2]);
1494 
1497 
1498 
1499  VMOVE(pt, p);
1500  pt[0] += 0.05;
1502  VMOVE(pt, p);
1503  pt[0] -= 0.05;
1505 
1506  VMOVE(pt, p);
1507  pt[1] += 0.05;
1509  VMOVE(pt, p);
1510  pt[1] -= 0.05;
1512 
1513  VMOVE(pt, p);
1514  pt[2] += 0.05;
1516  VMOVE(pt, p);
1517  pt[2] -= 0.05;
1519 
1521 }
1522 
1523 
1524 HIDDEN void
1525 show_broken_e(struct bn_vlblock *vbp, const struct edgeuse *eu)
1526 {
1527  pointp_t p0, p1;
1528  point_t end0, end1;
1529  vect_t v;
1530  struct bu_list *vh;
1531 
1532  NMG_CK_VERTEXUSE(eu->vu_p);
1533  NMG_CK_VERTEX(eu->vu_p->v_p);
1534  NMG_CK_VERTEX_G(eu->vu_p->v_p->vg_p);
1535  NMG_CK_VERTEXUSE(eu->eumate_p->vu_p);
1536  NMG_CK_VERTEX(eu->eumate_p->vu_p->v_p);
1537  NMG_CK_VERTEX_G(eu->eumate_p->vu_p->v_p->vg_p);
1538 
1539  NMG_INDEX_RETURN_IF_SET_ELSE_SET(broken_tab, eu->e_p->index);
1540 
1541  p0 = eu->vu_p->v_p->vg_p->coord;
1542  p1 = eu->eumate_p->vu_p->v_p->vg_p->coord;
1543 
1544  /* leave a little room between the edge endpoints and the vertex
1545  * compute endpoints by forming a vector between verts, scale
1546  * vector, and modify points
1547  */
1548  VSUB2SCALE(v, p1, p0, 0.90);
1549  VADD2(end0, p0, v);
1550  VSUB2(end1, p1, v);
1551 
1552 
1553  PICK_BROKEN_COLOR(eu->e_p);
1554  if (broken_color == 4) {
1555  PICK_BROKEN_COLOR(eu);
1556  }
1557 
1558  vh = rt_vlblock_find(vbp,
1559  broken_colors[broken_color][0], broken_colors[broken_color][1], broken_colors[broken_color][2]);
1560 
1561  RT_ADD_VLIST(vh, end0, BN_VLIST_LINE_MOVE);
1562  RT_ADD_VLIST(vh, end1, BN_VLIST_LINE_DRAW);
1563 
1564  show_broken_vu(vbp, eu->vu_p);
1565  show_broken_vu(vbp, eu->eumate_p->vu_p);
1566 
1567 }
1568 
1569 
1570 static void
1571 show_broken_eu(struct bn_vlblock *vbp, const struct edgeuse *eu, int fancy)
1572 {
1573  struct bu_list *vh;
1574  int red, green, blue;
1575  point_t base = VINIT_ZERO;
1576  point_t tip = VINIT_ZERO;
1577  point_t radial_tip = VINIT_ZERO;
1578  point_t next_base = VINIT_ZERO;
1579 
1580  NMG_CK_EDGEUSE(eu);
1581  NMG_CK_EDGE(eu->e_p);
1582 
1583  show_broken_e(vbp, eu);
1584 
1585  if (!fancy) return;
1586 
1587  /* paint the edgeuse lines */
1588  if (*eu->up.magic_p == NMG_LOOPUSE_MAGIC &&
1589  *eu->up.lu_p->up.magic_p == NMG_FACEUSE_MAGIC) {
1590 
1591  red = broken_colors[broken_color][0];
1592  green = broken_colors[broken_color][1];
1593  blue = broken_colors[broken_color][2];
1594 
1595  nmg_eu_coords(eu, base, tip);
1596  if (eu->up.lu_p->up.fu_p->orientation == OT_SAME)
1597  red += 50;
1598  else if (eu->up.lu_p->up.fu_p->orientation == OT_OPPOSITE)
1599  red -= 50;
1600  else
1601  red = green = blue = 255;
1602 
1603  vh = rt_vlblock_find(vbp, red, green, blue);
1604  RT_ADD_VLIST(vh, base, BN_VLIST_LINE_MOVE);
1605  RT_ADD_VLIST(vh, tip, BN_VLIST_LINE_DRAW);
1606 
1607  nmg_eu_radial(eu, radial_tip);
1608  vh = rt_vlblock_find(vbp, red, green-20, blue);
1609  RT_ADD_VLIST(vh, tip, BN_VLIST_LINE_MOVE);
1610  RT_ADD_VLIST(vh, radial_tip, BN_VLIST_LINE_DRAW);
1611 
1612  nmg_eu_next_base(eu, next_base);
1613  vh = rt_vlblock_find(vbp, 0, 100, 0);
1614  RT_ADD_VLIST(vh, tip, BN_VLIST_LINE_MOVE);
1615  RT_ADD_VLIST(vh, next_base, BN_VLIST_LINE_DRAW);
1616  }
1617 
1618 }
1619 
1620 
1621 static void
1622 show_broken_lu(struct bn_vlblock *vbp, const struct loopuse *lu, int fancy)
1623 {
1624  register struct edgeuse *eu;
1625  struct bu_list *vh;
1626  vect_t n;
1627 
1628  NMG_CK_LOOPUSE(lu);
1629 
1630  if (BU_LIST_FIRST_MAGIC(&lu->down_hd)==NMG_VERTEXUSE_MAGIC) {
1631  register struct vertexuse *vu;
1632  vu = BU_LIST_FIRST(vertexuse, &lu->down_hd);
1633  show_broken_vu(vbp, vu);
1634  return;
1635  }
1636 
1637  if (RTG.NMG_debug & DEBUG_GRAPHCL) {
1638  for (BU_LIST_FOR(eu, edgeuse, &lu->down_hd))
1639  show_broken_eu(vbp, eu, fancy);
1640  }
1641 
1642  /* Draw colored polygons for the actual face loops */
1643  /* Faces are not classified, only loops */
1644  /* This can obscure the edge/vertex info */
1645  PICK_BROKEN_COLOR(lu->l_p);
1646  vh = rt_vlblock_find(vbp,
1647  broken_colors[broken_color][0], broken_colors[broken_color][1], broken_colors[broken_color][2]);
1648 
1649  if (*lu->up.magic_p == NMG_FACEUSE_MAGIC) {
1650  NMG_GET_FU_NORMAL(n, lu->up.fu_p);
1651  } else {
1652  /* For wire loops, use a constant normal */
1653  VSET(n, 0, 0, 1);
1654  }
1655 
1656  if ((RTG.NMG_debug & (DEBUG_GRAPHCL|DEBUG_PL_LOOP)) == (DEBUG_PL_LOOP)) {
1657  /* If only DEBUG_PL_LOOP set, just draw lu as wires */
1658  nmg_lu_to_vlist(vh, lu, 0, n);
1659  } else if ((RTG.NMG_debug & (DEBUG_GRAPHCL|DEBUG_PL_LOOP)) == (DEBUG_GRAPHCL|DEBUG_PL_LOOP)) {
1660  /* Draw as polygons if both set */
1661  nmg_lu_to_vlist(vh, lu, 1, n);
1662  } else {
1663  /* If only DEBUG_GRAPHCL set, don't draw lu's at all */
1664  }
1665 }
1666 
1667 
1668 static void
1669 show_broken_fu(struct bn_vlblock *vbp, const struct faceuse *fu, int fancy)
1670 {
1671  register struct loopuse *lu;
1672 
1673  NMG_CK_FACEUSE(fu);
1674  for (BU_LIST_FOR(lu, loopuse, &fu->lu_hd)) {
1675  show_broken_lu(vbp, lu, fancy);
1676  }
1677 }
1678 
1679 
1680 static void
1681 show_broken_s(struct bn_vlblock *vbp, const struct shell *s, int fancy)
1682 {
1683  struct faceuse *fu;
1684  struct loopuse *lu;
1685  struct edgeuse *eu;
1686 
1687  NMG_CK_SHELL(s);
1688  for (BU_LIST_FOR(fu, faceuse, &s->fu_hd))
1689  show_broken_fu(vbp, fu, fancy);
1690  for (BU_LIST_FOR(lu, loopuse, &s->lu_hd))
1691  show_broken_lu(vbp, lu, fancy);
1692  for (BU_LIST_FOR(eu, edgeuse, &s->eu_hd))
1693  show_broken_eu(vbp, eu, fancy);
1694  if (s->vu_p)
1695  show_broken_vu(vbp, s->vu_p);
1696 }
1697 static void
1698 show_broken_r(struct bn_vlblock *vbp, const struct nmgregion *r, int fancy)
1699 {
1700  register struct shell *s;
1701 
1702  NMG_CK_REGION(r);
1703  for (BU_LIST_FOR(s, shell, & r->s_hd))
1704  show_broken_s(vbp, s, fancy);
1705 }
1706 
1707 
1708 static void
1709 show_broken_m(struct bn_vlblock *vbp, const struct model *m, int fancy)
1710 {
1711  register struct nmgregion *r;
1712 
1713  NMG_CK_MODEL(m);
1714  for (BU_LIST_FOR(r, nmgregion, &m->r_hd))
1715  show_broken_r(vbp, r, fancy);
1716 }
1717 
1718 
1719 static int stepalong = 0;
1720 
1721 void
1723 {
1724  stepalong=1;
1725 }
1726 
1727 
1728 /**
1729  * XXX Needs new name, with nmg_ prefix, and a stronger indication
1730  * that this is a graphical display of classifier operation.
1731  */
1732 void
1733 nmg_show_broken_classifier_stuff(uint32_t *p, char **classlist, int all_new, int fancy, const char *a_string)
1734 {
1735  static struct bn_vlblock *vbp = (struct bn_vlblock *)NULL;
1736  struct model *m;
1737 
1738 /* printf("showing broken stuff\n"); */
1739 
1740  global_classlist = classlist;
1741 
1742  nmg_class_nothing_broken = 0;
1743 
1744  if (!vbp)
1745  vbp = rt_vlblock_init();
1746  else if (all_new) {
1747  rt_vlblock_free(vbp);
1748  vbp = (struct bn_vlblock *)NULL;
1749  vbp = rt_vlblock_init();
1750  }
1751 
1752  m = nmg_find_model(p);
1753  /* get space for list of items processed */
1754  if (!broken_tab) {
1755  broken_tab = (long *)bu_calloc(m->maxindex+1, sizeof(long),
1756  "nmg_vlblock_s tab[]");
1757  broken_tab_len = m->maxindex+1;
1758  } else {
1759  if (broken_tab_len < m->maxindex+1) {
1760  bu_log("nmg_show_broken_classifier_stuff() maxindex increased! was %d, now %ld\n",
1761  broken_tab_len, m->maxindex+1);
1762  broken_tab = (long *)bu_realloc((char *)broken_tab,
1763  (m->maxindex+1) * sizeof(long),
1764  "nmg_vlblock_s tab[] enlargement");
1765  broken_tab_len = m->maxindex+1;
1766  }
1767  if (all_new) {
1768  memset((char *)broken_tab, 0, (m->maxindex+1) * sizeof(long));
1769  }
1770  }
1771 
1772 
1773  switch (*p) {
1774  case NMG_MODEL_MAGIC:
1775  show_broken_m(vbp, (struct model *)p, fancy);
1776  break;
1777  case NMG_REGION_MAGIC:
1778  show_broken_r(vbp, (struct nmgregion *)p, fancy);
1779  break;
1780  case NMG_SHELL_MAGIC:
1781  show_broken_s(vbp, (struct shell *)p, fancy);
1782  break;
1783  case NMG_FACE_MAGIC:
1784  show_broken_fu(vbp, ((struct face *)p)->fu_p, fancy);
1785  break;
1786  case NMG_FACEUSE_MAGIC:
1787  show_broken_fu(vbp, (struct faceuse *)p, fancy);
1788  break;
1789  case NMG_LOOPUSE_MAGIC:
1790  show_broken_lu(vbp, (struct loopuse *)p, fancy);
1791  break;
1792  case NMG_EDGE_MAGIC:
1793  show_broken_eu(vbp, ((struct edge *)p)->eu_p, fancy);
1794  break;
1795  case NMG_EDGEUSE_MAGIC:
1796  show_broken_eu(vbp, (struct edgeuse *)p, fancy);
1797  break;
1798  case NMG_VERTEXUSE_MAGIC:
1799  show_broken_vu(vbp, (struct vertexuse *)p);
1800  break;
1801  default:
1802  bu_log("Unknown magic number %u %x %zu %p\n",
1803  (unsigned)*p, (unsigned)*p, (size_t)p, (void *)p);
1804  break;
1805  }
1806 
1807  /*
1808  * Cause animation of boolean operation as it proceeds! The
1809  * "copy" flag on nmg_vlblock_anim_upcall() means that the vlist
1810  * will remain, undisturbed, for further use.
1811  */
1813  void (*cur_sigint)(int);
1814 
1815  /* need to cast nmg_vlblock_anim_upcall pointer for actual use as a function */
1816  void (*cfp)(struct bn_vlblock *, int, int);
1817  cfp = (void (*)(struct bn_vlblock *, int, int))nmg_vlblock_anim_upcall;
1818 
1819  if (!a_string) {
1820  cfp(vbp,
1821  (RTG.NMG_debug&DEBUG_PL_SLOW) ? US_DELAY : 0,
1822  1);
1823  } else {
1824 
1825  bu_log("NMG Intermediate display Ctrl-C to continue (%s)\n", a_string);
1826  cur_sigint = signal(SIGINT, nmg_plot_sigstepalong);
1827 
1828  cfp(vbp,
1829  (RTG.NMG_debug&DEBUG_PL_SLOW) ? US_DELAY : 0,
1830  1);
1831 
1832  for (stepalong = 0; !stepalong;) {
1833  (*nmg_mged_debug_display_hack)();
1834  }
1835  signal(SIGINT, cur_sigint);
1836  bu_log("Continuing\n");
1837  }
1838  } else {
1839  /* Non interactive, drop a plot file */
1840  char buf[128];
1841  static int num = 0;
1842  FILE *fp;
1843 
1844  sprintf(buf, "cbroke%d.plot3", num++);
1845  fp = fopen(buf, "wb");
1846  if (fp) {
1847  rt_plot_vlblock(fp, vbp);
1848  fclose(fp);
1849  bu_log("overlay %s for %s\n", buf, a_string);
1850  }
1851 
1852  rt_vlblock_free(vbp);
1853  vbp = (struct bn_vlblock *)NULL;
1854  bu_free((char *)broken_tab, "broken_tab");
1855  broken_tab = (long *)NULL;
1856  broken_tab_len = 0;
1857  }
1858 }
1859 
1860 
1861 void
1862 nmg_face_plot(const struct faceuse *fu)
1863 {
1864  FILE *fp;
1865  char name[32];
1866  struct model *m;
1867  struct bn_vlblock *vbp;
1868  long *tab;
1869  int fancy;
1870  static int num = 1;
1871 
1872  if ((RTG.NMG_debug & (DEBUG_PLOTEM|DEBUG_PL_ANIM)) == 0) return;
1873 
1874  NMG_CK_FACEUSE(fu);
1875 
1876  m = nmg_find_model((uint32_t *)fu);
1877  NMG_CK_MODEL(m);
1878 
1879  /* get space for list of items processed */
1880  tab = (long *)bu_calloc(m->maxindex+1, sizeof(long),
1881  "nmg_face_plot tab[]");
1882 
1883  vbp = rt_vlblock_init();
1884 
1885  fancy = 3; /* show both types of edgeuses */
1886  nmg_vlblock_fu(vbp, fu, tab, fancy);
1887 
1888  if (RTG.NMG_debug & DEBUG_PLOTEM) {
1889  (void)sprintf(name, "face%d.plot3", num++);
1890  bu_log("overlay %s\n", name);
1891  fp=fopen(name, "wb");
1892  if (fp == (FILE *)NULL) {
1893  perror(name);
1894  return;
1895  }
1896  rt_plot_vlblock(fp, vbp);
1897  (void)fclose(fp);
1898  }
1899 
1900  if (RTG.NMG_debug & DEBUG_PL_ANIM) {
1901  /* Cause animation of boolean operation as it proceeds! */
1903  /* if requested, delay 3/4 second */
1904  /* need to cast nmg_vlblock_anim_upcall pointer for actual use as a function */
1905  void (*cfp)(struct bn_vlblock *, int, int);
1906  cfp = (void (*)(struct bn_vlblock *, int, int))nmg_vlblock_anim_upcall;
1907  cfp(vbp,
1908  (RTG.NMG_debug&DEBUG_PL_SLOW) ? 750000 : 0,
1909  0);
1910  } else {
1911  bu_log("null nmg_vlblock_anim_upcall, no animation\n");
1912  }
1913  }
1914  rt_vlblock_free(vbp);
1915  bu_free((char *)tab, "nmg_face_plot tab[]");
1916 
1917 }
1918 
1919 
1920 /**
1921  * Just like nmg_face_plot, except it draws two faces each iteration.
1922  */
1923 void
1924 nmg_2face_plot(const struct faceuse *fu1, const struct faceuse *fu2)
1925 {
1926  struct model *m;
1927  struct bn_vlblock *vbp;
1928  long *tab;
1929  int fancy;
1930 
1931  if (! (RTG.NMG_debug & DEBUG_PL_ANIM)) return;
1932 
1933  NMG_CK_FACEUSE(fu1);
1934  NMG_CK_FACEUSE(fu2);
1935 
1936  m = nmg_find_model((uint32_t *)fu1);
1937  NMG_CK_MODEL(m);
1938 
1939  /* get space for list of items processed */
1940  tab = (long *)bu_calloc(m->maxindex+1, sizeof(long),
1941  "nmg_2face_plot tab[]");
1942 
1943  vbp = rt_vlblock_init();
1944 
1945  fancy = 3; /* show both types of edgeuses */
1946  nmg_vlblock_fu(vbp, fu1, tab, fancy);
1947  nmg_vlblock_fu(vbp, fu2, tab, fancy);
1948 
1949  /* Cause animation of boolean operation as it proceeds! */
1951  /* if requested, delay 3/4 second */
1952  /* need to cast nmg_vlblock_anim_upcall pointer for actual use as a function */
1953  void (*cfp)(struct bn_vlblock *, int, int);
1954  cfp = (void (*)(struct bn_vlblock *, int, int))nmg_vlblock_anim_upcall;
1955  cfp(vbp,
1956  (RTG.NMG_debug&DEBUG_PL_SLOW) ? 750000 : 0,
1957  0);
1958  } else {
1959  bu_log("null nmg_vlblock_anim_upcall, no animation\n");
1960  }
1961  rt_vlblock_free(vbp);
1962  bu_free((char *)tab, "nmg_2face_plot tab[]");
1963 
1964 }
1965 
1966 
1967 /**
1968  * Plot the loop, and a ray from vu1 to vu2.
1969  */
1970 void
1971 nmg_face_lu_plot(const struct loopuse *lu, const struct vertexuse *vu1, const struct vertexuse *vu2)
1972 {
1973  FILE *fp;
1974  struct model *m;
1975  long *b;
1976  char buf[128];
1977  static int num = 0;
1978  vect_t dir;
1979  point_t p1, p2;
1980 
1981  if (!(RTG.NMG_debug&DEBUG_PLOTEM)) return;
1982 
1983  NMG_CK_LOOPUSE(lu);
1984  NMG_CK_VERTEXUSE(vu1);
1985  NMG_CK_VERTEXUSE(vu2);
1986 
1987  m = nmg_find_model((uint32_t *)lu);
1988  sprintf(buf, "loop%d.plot3", num++);
1989 
1990  fp = fopen(buf, "wb");
1991  if (fp == NULL) {
1992  perror(buf);
1993  return;
1994  }
1995  b = (long *)bu_calloc(m->maxindex, sizeof(long), "nmg_face_lu_plot flag[]");
1996  nmg_pl_lu(fp, lu, b, 255, 0, 0);
1997 
1998  /*
1999  * Two yellow lines for the ray.
2000  * Overshoot edge by +/-10%, for visibility.
2001  * Don't draw over top of the actual edge, it might hide verts.
2002  */
2003  pl_color(fp, 255, 255, 0);
2004  VSUB2(dir, vu2->v_p->vg_p->coord, vu1->v_p->vg_p->coord);
2005  VJOIN1(p1, vu1->v_p->vg_p->coord, -0.1, dir);
2006  pdv_3line(fp, p1, vu1->v_p->vg_p->coord);
2007  VJOIN1(p2, vu1->v_p->vg_p->coord, 1.1, dir);
2008  pdv_3line(fp, vu2->v_p->vg_p->coord, p2);
2009 
2010  fclose(fp);
2011  bu_log("overlay %s\n", buf);
2012  bu_free((char *)b, "nmg_face_lu_plot flag[]");
2013 }
2014 
2015 
2016 /**
2017  * Plot the loop, a ray from vu1 to vu2, and the left vector.
2018  */
2019 void
2020 nmg_plot_lu_ray(const struct loopuse *lu, const struct vertexuse *vu1, const struct vertexuse *vu2, const fastf_t *left)
2021 {
2022  FILE *fp;
2023  struct model *m;
2024  long *b;
2025  char buf[128];
2026  static int num = 0;
2027  vect_t dir;
2028  point_t p1, p2;
2029  fastf_t left_mag;
2030 
2031  if (!(RTG.NMG_debug&DEBUG_PLOTEM)) return;
2032 
2033  NMG_CK_LOOPUSE(lu);
2034  NMG_CK_VERTEXUSE(vu1);
2035  NMG_CK_VERTEXUSE(vu2);
2036 
2037  m = nmg_find_model((uint32_t *)lu);
2038  sprintf(buf, "loop%d.plot3", num++);
2039 
2040  fp = fopen(buf, "wb");
2041  if (fp == NULL) {
2042  perror(buf);
2043  return;
2044  }
2045  b = (long *)bu_calloc(m->maxindex, sizeof(long), "nmg_plot_lu_ray flag[]");
2046  nmg_pl_lu(fp, lu, b, 255, 0, 0);
2047 
2048  /*
2049  * Two yellow lines for the ray, and a third for the left vector.
2050  * Overshoot edge by +/-10%, for visibility.
2051  * Don't draw over top of the actual edge, it might hide verts.
2052  */
2053  pl_color(fp, 255, 255, 0);
2054  VSUB2(dir, vu2->v_p->vg_p->coord, vu1->v_p->vg_p->coord);
2055  VJOIN1(p1, vu1->v_p->vg_p->coord, -0.1, dir);
2056  pdv_3line(fp, p1, vu1->v_p->vg_p->coord);
2057  VJOIN1(p2, vu1->v_p->vg_p->coord, 1.1, dir);
2058  pdv_3line(fp, vu2->v_p->vg_p->coord, p2);
2059 
2060  /* The left vector */
2061  left_mag = 0.1 * MAGNITUDE(dir);
2062  VJOIN1(p2, p1, left_mag, left);
2063  pdv_3line(fp, p1, p2);
2064 
2065  fclose(fp);
2066  bu_log("overlay %s\n", buf);
2067  bu_free((char *)b, "nmg_plot_lu_ray flag[]");
2068 }
2069 
2070 
2071 void
2072 nmg_plot_ray_face(const char *fname, fastf_t *pt, const fastf_t *dir, const struct faceuse *fu)
2073 {
2074  FILE *fp;
2075  long *b;
2076  point_t pp;
2077  static int i = 0;
2078  char name[1024] = {0};
2079 
2080  if (! (RTG.NMG_debug & DEBUG_NMGRT))
2081  return;
2082 
2083  snprintf(name, 1024, "%s%0d.plot3", fname, i++);
2084  fp = fopen(name, "w");
2085  if (fp == (FILE *)NULL) {
2086  perror(name);
2087  bu_log("plot_ray_face cannot open %s", name);
2088  bu_bomb("aborting");
2089  }
2090 
2091  b = (long *)bu_calloc(fu->s_p->r_p->m_p->maxindex, sizeof(long), "bit vec");
2092 
2093  nmg_pl_fu(fp, fu, b, 200, 200, 200);
2094 
2095  bu_free((char *)b, "bit vec");
2096 
2097  VSCALE(pp, dir, 1000.0);
2098  VADD2(pp, pt, pp);
2099  pdv_3line(fp, pt, pp);
2100  (void)fclose(fp);
2101  bu_log("overlay %s\n", name);
2102 }
2103 
2104 
2105 /**
2106  * Draw and label all the loopuses gathered around this edgeuse.
2107  *
2108  * Called by nmg_radial_join_eu().
2109  */
2110 void
2111 nmg_plot_lu_around_eu(const char *prefix, const struct edgeuse *eu, const struct bn_tol *tol)
2112 {
2113  char file[256];
2114  static int num = 0;
2115  struct model *m;
2116  struct bn_vlblock *vbp;
2117  long *tab;
2118  const struct edgeuse *eur;
2119  FILE *fp;
2120 
2121  NMG_CK_EDGEUSE(eu);
2122  BN_CK_TOL(tol);
2123 
2124  snprintf(file, 256, "%s%0d.plot3", prefix, num++);
2125  bu_log("overlay %s\n", file);
2126  fp = fopen(file, "wb");
2127  if (fp == (FILE *)NULL) {
2128  bu_log("plot_lu_around_eu() cannot open %s", file);
2129  return;
2130  }
2131 
2132  m = nmg_find_model((uint32_t *)eu);
2133  NMG_CK_MODEL(m);
2134  tab = (long *)bu_calloc(m->maxindex, sizeof(long), "bit vec");
2135 
2136  vbp = rt_vlblock_init();
2137 
2138  /* Draw all the left vectors, and a fancy edgeuse plot */
2139  nmg_vlblock_around_eu(vbp, eu, tab, 3, tol);
2140 
2141  eur = eu;
2142  do {
2143  NMG_CK_EDGEUSE(eur);
2144 
2145  if (*eur->up.magic_p == NMG_LOOPUSE_MAGIC) {
2146  /* Draw this loop in non-fancy format, for context */
2147  nmg_vlblock_lu(vbp, eur->up.lu_p, tab, 80, 100, 170, 0);
2148  }
2149  eur = eur->radial_p->eumate_p;
2150  } while (eur != eu);
2151 
2152  rt_plot_vlblock(fp, vbp);
2153  (void)fclose(fp);
2154  rt_vlblock_free(vbp);
2155  bu_free((char *)tab, "bit vec");
2156 }
2157 
2158 
2159 /**
2160  * A routine to draw the entire surface of a face_g_snurb.
2161  * No handling of trimming curves is done.
2162  */
2163 int
2164 nmg_snurb_to_vlist(struct bu_list *vhead, const struct face_g_snurb *fg, int n_interior)
2165 
2166 
2167 /* typ. 10 */
2168 {
2169  register int i;
2170  register int j;
2171  register fastf_t * vp;
2172  struct knot_vector tkv1,
2173  tkv2,
2174  tau1,
2175  tau2;
2176  struct face_g_snurb *r, *c;
2177  int coords;
2178 
2179  BU_CK_LIST_HEAD(vhead);
2180  NMG_CK_FACE_G_SNURB(fg);
2181 
2182  rt_nurb_kvgen(&tkv1,
2183  fg->u.knots[0],
2184  fg->u.knots[fg->u.k_size-1], n_interior, (struct resource *)NULL);
2185 
2186  rt_nurb_kvgen(&tkv2,
2187  fg->v.knots[0],
2188  fg->v.knots[fg->v.k_size-1], n_interior, (struct resource *)NULL);
2189 
2190  rt_nurb_kvmerge(&tau1, &tkv1, &fg->u, (struct resource *)NULL);
2191  rt_nurb_kvmerge(&tau2, &tkv2, &fg->v, (struct resource *)NULL);
2192 
2193 /** nmg_hack_snurb(&n, fg); / XXX */
2194 
2195  r = rt_nurb_s_refine(fg, RT_NURB_SPLIT_COL, &tau2, (struct resource *)NULL);
2196  NMG_CK_SNURB(r);
2197  c = rt_nurb_s_refine(r, RT_NURB_SPLIT_ROW, &tau1, (struct resource *)NULL);
2198  NMG_CK_SNURB(c);
2199 
2200  coords = RT_NURB_EXTRACT_COORDS(c->pt_type);
2201 
2202  if (RT_NURB_IS_PT_RATIONAL(c->pt_type)) {
2203  vp = c->ctl_points;
2204  for (i= 0; i < c->s_size[0] * c->s_size[1]; i++) {
2205  fastf_t one_over_vp;
2206  vp[0] *= (one_over_vp = 1/vp[3]);
2207  vp[1] *= one_over_vp;
2208  vp[2] *= one_over_vp;
2209  vp[3] *= one_over_vp;
2210  vp += coords;
2211  }
2212  }
2213 
2214  vp = c->ctl_points;
2215  for (i = 0; i < c->s_size[0]; i++) {
2216  RT_ADD_VLIST(vhead, vp, BN_VLIST_LINE_MOVE);
2217  vp += coords;
2218  for (j = 1; j < c->s_size[1]; j++) {
2219  RT_ADD_VLIST(vhead, vp, BN_VLIST_LINE_DRAW);
2220  vp += coords;
2221  }
2222  }
2223 
2224  for (j = 0; j < c->s_size[1]; j++) {
2225  int stride;
2226 
2227  stride = c->s_size[1] * coords;
2228  vp = &c->ctl_points[j * coords];
2229  RT_ADD_VLIST(vhead, vp, BN_VLIST_LINE_MOVE);
2230  vp += stride;
2231  for (i = 1; i < c->s_size[0]; i++) {
2232  RT_ADD_VLIST(vhead, vp, BN_VLIST_LINE_DRAW);
2233  vp += stride;
2234  }
2235  }
2236  rt_nurb_free_snurb(c, (struct resource *)NULL);
2237  rt_nurb_free_snurb(r, (struct resource *)NULL);
2238 
2239  bu_free((char *) tau1.knots, "rt_nurb_plot:tau1.knots");
2240  bu_free((char *) tau2.knots, "rt_nurb_plot:tau2.knots");
2241  bu_free((char *) tkv1.knots, "rt_nurb_plot:tkv1>knots");
2242  bu_free((char *) tkv2.knots, "rt_nurb_plot:tkv2.knots");
2243 
2244  return 0;
2245 }
2246 
2247 
2248 /**
2249  * Draw interior points on a cnurb curve.
2250  *
2251  * The endpoints are not drawn, as those points are (should) match the
2252  * vertices at the end of the edgeuse, and are handled by the caller.
2253  *
2254  * Special processing is performed for the order <= 0 (linear) cnurbs.
2255  *
2256  * If the curve is on a snurb face, it is in parameter space.
2257  * If the curve is on a planar face, it is in XYZ space.
2258  */
2259 void
2260 nmg_cnurb_to_vlist(struct bu_list *vhead, const struct edgeuse *eu, int n_interior, int cmd)
2261 
2262 
2263 /* typ. 10 */
2264 /* BN_VLIST_LINE_DRAW, etc. */
2265 {
2266  const struct edge_g_cnurb *eg;
2267  const struct faceuse *fu;
2268  register int i;
2269  register fastf_t *vp = (fastf_t *)NULL;
2270  struct edge_g_cnurb n;
2271  const struct edge_g_cnurb *c;
2272  int coords;
2273 
2274  memset(&n, 0, sizeof(struct edge_g_cnurb));
2275 
2276  BU_CK_LIST_HEAD(vhead);
2277  NMG_CK_EDGEUSE(eu);
2278  eg = eu->g.cnurb_p;
2279  NMG_CK_EDGE_G_CNURB(eg);
2280 
2281  fu = nmg_find_fu_of_eu(eu); /* may return NULL */
2282  NMG_CK_FACEUSE(fu);
2283  if (RTG.NMG_debug & DEBUG_BASIC) {
2284  bu_log("nmg_cnurb_to_vlist() eu=%p, n=%d, order=%d\n",
2285  (void *)eu, n_interior, eg->order);
2286  }
2287 
2288  if (eg->order <= 0) {
2289  /* linear cnurb on planar face -- no intermediate points to draw */
2290  if (*fu->f_p->g.magic_p == NMG_FACE_G_PLANE_MAGIC)
2291  return;
2292 
2293  /* linear cnurb on snurb face -- cnurb ctl pts are UV */
2294  n.order = 2;
2295  n.l.magic = NMG_EDGE_G_CNURB_MAGIC;
2296  n.c_size = 2;
2297  rt_nurb_gen_knot_vector(&n.k, n.order, 0.0, 1.0, (struct resource *)NULL);
2298  n.pt_type = RT_NURB_MAKE_PT_TYPE(2, RT_NURB_PT_UV, RT_NURB_PT_NONRAT);
2299  n.ctl_points = (fastf_t *)bu_malloc(
2300  sizeof(fastf_t) * RT_NURB_EXTRACT_COORDS(n.pt_type) *
2301  n.c_size, "nmg_cnurb_to_vlist() order0 ctl_points[]");
2302  /* Set ctl points to parametric values */
2303  NMG_CK_VERTEXUSE_A_CNURB(eu->vu_p->a.cnurb_p);
2304  n.ctl_points[0] = eu->vu_p->a.cnurb_p->param[0];
2305  n.ctl_points[1] = eu->vu_p->a.cnurb_p->param[1];
2306  n.ctl_points[2] = eu->eumate_p->vu_p->a.cnurb_p->param[0];
2307  n.ctl_points[3] = eu->eumate_p->vu_p->a.cnurb_p->param[1];
2308  c = &n;
2309  } else {
2310  /* Just use eg */
2311  c = eg;
2312  }
2313 
2314  NMG_CK_CNURB(c);
2315 
2316  coords = RT_NURB_EXTRACT_COORDS(c->pt_type);
2317 
2318  if (*fu->f_p->g.magic_p == NMG_FACE_G_PLANE_MAGIC) {
2319  /* cnurb on planar face -- ctl points are XYZ */
2320 
2321  vp = c->ctl_points;
2322  /* Omit first and last points */
2323  for (i = 1; i < c->c_size-1; i++) {
2324  RT_ADD_VLIST(vhead, vp, cmd);
2325  vp += coords;
2326  }
2327  } else {
2328  const struct face_g_snurb *s;
2329  fastf_t final[4];
2330  fastf_t inv_homo;
2331  fastf_t param_delta;
2332  fastf_t crv_param;
2333 
2334  /* cnurb on spline face -- ctl points are UV or UVW */
2335  if (coords != 2 && !RT_NURB_IS_PT_RATIONAL(c->pt_type)) bu_log("nmg_cnurb_to_vlist() coords=%d\n", coords);
2336  s = fu->f_p->g.snurb_p;
2337 
2338  /* This section uses rt_nurb_c_eval(), but rt_nurb_c_refine is likely faster.
2339  * XXXX Need a way to selectively and recursively refine curve to avoid
2340  * feeding rt_nurb_s_eval() parameters outside domain of surface.
2341  */
2342  param_delta = (c->k.knots[c->k.k_size-1] - c->k.knots[0])/(fastf_t)(n_interior+1);
2343  crv_param = c->k.knots[0];
2344  for (i = 0; i < n_interior; i++) {
2345  point_t uvw;
2346 
2347  /* evaluate curve at parameter values */
2348  crv_param += param_delta;
2349 
2350  VSETALL(uvw, 0);
2351 
2352  rt_nurb_c_eval(c, crv_param, uvw);
2353 
2354  if (RT_NURB_IS_PT_RATIONAL(c->pt_type)) {
2355  uvw[0] = uvw[0]/uvw[2];
2356  uvw[1] = uvw[1]/uvw[2];
2357  }
2358 
2359  /* convert 'uvw' from UV coord to XYZ coord via surf! */
2360  rt_nurb_s_eval(s, uvw[0], uvw[1], final);
2361 
2362  if (RT_NURB_IS_PT_RATIONAL(s->pt_type)) {
2363  /* divide out homogeneous coordinate */
2364  inv_homo = 1.0/final[3];
2365  VSCALE(final, final, inv_homo);
2366  }
2367 
2368  RT_ADD_VLIST(vhead, final, cmd);
2369  vp += coords;
2370  }
2371  }
2372 
2373  if (eg->order <= 0) {
2374  bu_free((char *)n.k.knots, "nmg_cnurb_to_vlist() n.knot.knots");
2375  bu_free((char *)n.ctl_points, "nmg_cnurb_to_vlist() ctl_points");
2376  }
2377 }
2378 
2379 
2380 /*
2381  * Local Variables:
2382  * mode: C
2383  * tab-width: 8
2384  * indent-tabs-mode: t
2385  * c-file-style: "stroustrup"
2386  * End:
2387  * ex: shiftwidth=4 tabstop=8
2388  */
void nmg_pl_s(FILE *fp, const struct shell *s)
Definition: nmg_plot.c:746
void nmg_vlblock_around_eu(struct bn_vlblock *vbp, const struct edgeuse *arg_eu, long *tab, int fancy, const struct bn_tol *tol)
Definition: nmg_plot.c:1022
#define NMG_MODEL_MAGIC
Definition: magic.h:133
#define BU_LIST_PNEXT_CIRC(structure, p)
Definition: list.h:442
#define BU_LIST_FOR(p, structure, hp)
Definition: list.h:365
void nmg_pl_m(FILE *fp, const struct model *m)
Definition: nmg_plot.c:782
char filename[MAXLENGTH]
Definition: human.c:105
void nmg_snurb_fu_get_norm(const struct faceuse *fu, const fastf_t u, const fastf_t v, fastf_t *norm)
Definition: nmg_misc.c:192
#define NMG_EDGEUSE_MAGIC
Definition: magic.h:120
void nmg_vlblock_eu(struct bn_vlblock *vbp, const struct edgeuse *eu, long *tab, int red, int green, int blue, int fancy)
Definition: nmg_plot.c:861
void rt_nurb_free_snurb(struct face_g_snurb *srf, struct resource *res)
Definition: nurb_util.c:127
void bu_log(const char *,...) _BU_ATTR_PRINTF12
Definition: log.c:176
struct faceuse * nmg_find_fu_of_eu(const struct edgeuse *eu)
Definition: nmg_info.c:270
void rt_vlblock_free(struct bn_vlblock *vbp)
Definition: vlist.c:78
HIDDEN void show_broken_vu(struct bn_vlblock *vbp, const struct vertexuse *vu)
Definition: nmg_plot.c:1471
Definition: list.h:118
#define NMG_EDGE_MAGIC
Definition: magic.h:123
#define NMG_SHELL_MAGIC
Definition: magic.h:142
void pdv_3move(register FILE *plotfp, const fastf_t *pt)
Definition: plot3.c:618
#define US_DELAY
Definition: nmg_plot.c:57
void nmg_eu_to_vlist(struct bu_list *vhead, const struct bu_list *eu_hd)
Definition: nmg_plot.c:94
void nmg_vlblock_r(struct bn_vlblock *vbp, const struct nmgregion *r, int fancy)
Definition: nmg_plot.c:1186
#define NMG_FACE_G_SNURB_MAGIC
Definition: magic.h:126
if lu s
Definition: nmg_mod.c:3860
void nmg_pl_comb_fu(int num1, int num2, const struct faceuse *fu1)
Definition: nmg_plot.c:1316
Definition: clone.c:90
struct bu_list rtg_vlfree
head of bn_vlist freelist
Definition: raytrace.h:1698
struct face_g_snurb * rt_nurb_s_refine(const struct face_g_snurb *srf, int dir, struct knot_vector *kv, struct resource *res)
Definition: nurb_refine.c:45
lu
Definition: nmg_mod.c:3855
#define VSET(a, b, c, d)
Definition: color.c:53
#define VSETALL(a, s)
Definition: color.c:54
void nmg_vlblock_v(struct bn_vlblock *vbp, const struct vertex *v, long *tab)
Definition: nmg_plot.c:802
void nmg_plot_sigstepalong(int i)
Definition: nmg_plot.c:1722
Header file for the BRL-CAD common definitions.
void nmg_cnurb_to_vlist(struct bu_list *vhead, const struct edgeuse *eu, int n_interior, int cmd)
Definition: nmg_plot.c:2260
void nmg_face_plot(const struct faceuse *fu)
Definition: nmg_plot.c:1862
void nmg_show_broken_classifier_stuff(uint32_t *p, char **classlist, int all_new, int fancy, const char *a_string)
Definition: nmg_plot.c:1733
struct bn_vlblock * rt_vlblock_init(void)
Definition: vlist.c:71
#define NMG_LOOPUSE_MAGIC
Definition: magic.h:130
void nmg_vlblock_s(struct bn_vlblock *vbp, const struct shell *s, int fancy)
Definition: nmg_plot.c:1134
#define HIDDEN
Definition: common.h:86
NMG_CK_LOOPUSE(lu)
#define BN_VLIST_POLY_MOVE
move to first poly vertex
Definition: vlist.h:85
void rt_nurb_gen_knot_vector(register struct knot_vector *new_knots, int order, fastf_t lower, fastf_t upper, struct resource *res)
Definition: nurb_knot.c:318
void * bu_malloc(size_t siz, const char *str)
Definition: malloc.c:314
void nmg_eu_2vecs_perp(fastf_t *xvec, fastf_t *yvec, fastf_t *zvec, const struct edgeuse *eu, const struct bn_tol *tol)
Definition: nmg_info.c:1237
struct bu_list * rt_vlblock_find(struct bn_vlblock *vbp, int r, int g, int b)
Definition: vlist.c:98
void nmg_vlblock_m(struct bn_vlblock *vbp, const struct model *m, int fancy)
Definition: nmg_plot.c:1200
void nmg_2face_plot(const struct faceuse *fu1, const struct faceuse *fu2)
Definition: nmg_plot.c:1924
Definition: color.c:49
void * memset(void *s, int c, size_t n)
void nmg_pl_fu(FILE *fp, const struct faceuse *fu, long *b, int red, int green, int blue)
Definition: nmg_plot.c:722
#define RT_ADD_VLIST(hd, pnt, draw)
Definition: raytrace.h:1865
uint32_t NMG_debug
debug bits for NMG's see nmg.h
Definition: raytrace.h:1699
#define NMG_FACE_MAGIC
Definition: magic.h:127
void nmg_vlblock_euleft(struct bu_list *vh, const struct edgeuse *eu, const fastf_t *center, const fastf_t *mat, const fastf_t *xvec, const fastf_t *yvec, double len, const struct bn_tol *tol)
Definition: nmg_plot.c:982
void * bu_calloc(size_t nelem, size_t elsize, const char *str)
Definition: malloc.c:321
void nmg_pl_eu(FILE *fp, const struct edgeuse *eu, long *b, int red, int green, int blue)
Definition: nmg_plot.c:658
void nmg_lu_to_vlist(struct bu_list *vhead, const struct loopuse *lu, int poly_markers, const vectp_t normal)
Definition: nmg_plot.c:140
void rt_nurb_kvmerge(struct knot_vector *new_knots, const struct knot_vector *kv1, const struct knot_vector *kv2, struct resource *res)
Definition: nurb_knot.c:147
#define BN_VLIST_POLY_START
pt[] has surface normal
Definition: vlist.h:84
void nmg_face_lu_plot(const struct loopuse *lu, const struct vertexuse *vu1, const struct vertexuse *vu2)
Definition: nmg_plot.c:1971
#define BN_VLIST_LINE_MOVE
Definition: vlist.h:82
#define BN_VLIST_LINE_DRAW
Definition: vlist.h:83
void nmg_pl_isect(const char *filename, const struct shell *s, const struct bn_tol *tol)
Definition: nmg_plot.c:1256
#define BU_LIST_PNEXT(structure, p)
Definition: list.h:422
void pl_label(register FILE *plotfp, const char *s)
Definition: plot3.c:244
void * bu_realloc(void *ptr, size_t siz, const char *str)
void nmg_pl_r(FILE *fp, const struct nmgregion *r)
Definition: nmg_plot.c:770
#define UNUSED(parameter)
Definition: common.h:239
void nmg_plot_lu_ray(const struct loopuse *lu, const struct vertexuse *vu1, const struct vertexuse *vu2, const fastf_t *left)
Definition: nmg_plot.c:2020
#define BN_VLIST_POLY_DRAW
subsequent poly vertex
Definition: vlist.h:86
void nmg_vlblock_lu(struct bn_vlblock *vbp, const struct loopuse *lu, long *tab, int red, int green, int blue, int fancy)
Definition: nmg_plot.c:1088
#define NMG_REGION_MAGIC
Definition: magic.h:137
Support for uniform tolerances.
Definition: tol.h:71
#define BN_CK_TOL(_p)
Definition: tol.h:82
#define BU_LIST_FIRST_MAGIC(hp)
Definition: list.h:416
void bn_vlist_3string(struct bu_list *vhead, struct bu_list *free_hd, const char *string, const point_t origin, const mat_t rot, double scale)
int nmg_find_eu_leftvec(fastf_t *left, const struct edgeuse *eu)
Definition: nmg_info.c:1274
#define NMG_VERTEXUSE_MAGIC
Definition: magic.h:145
void nmg_r_to_vlist(struct bu_list *vhead, const struct nmgregion *r, int poly_markers)
Definition: nmg_plot.c:404
struct fg_node fg
Definition: chull3d.cpp:80
void pl_color(register FILE *plotfp, int r, int g, int b)
Definition: plot3.c:325
void nmg_pl_lu(FILE *fp, const struct loopuse *lu, long *b, int red, int green, int blue)
Definition: nmg_plot.c:710
#define NMG_FACE_G_PLANE_MAGIC
Definition: magic.h:125
void pdv_3line(register FILE *plotfp, const fastf_t *a, const fastf_t *b)
Definition: plot3.c:642
#define BN_CK_VLBLOCK(_p)
Definition: vlist.h:177
oldeumate e_p eu_p
Definition: nmg_mod.c:3940
int nmg_class_nothing_broken
Definition: nmg_plot.c:1443
#define BU_LIST_PPREV_CIRC(structure, p)
Definition: list.h:450
void nmg_m_to_vlist(struct bu_list *vhead, struct model *m, int poly_markers)
Definition: nmg_plot.c:417
void nmg_pl_shell(FILE *fp, const struct shell *s, int fancy)
Definition: nmg_plot.c:758
void nmg_vlblock_e(struct bn_vlblock *vbp, const struct edge *e, long *tab, int red, int green, int blue)
Definition: nmg_plot.c:821
void nmg_pl_v(FILE *fp, const struct vertex *v, long *b)
Definition: nmg_plot.c:600
void nmg_plot_lu_around_eu(const char *prefix, const struct edgeuse *eu, const struct bn_tol *tol)
Definition: nmg_plot.c:2111
#define NMG_EDGE_G_CNURB_MAGIC
Definition: magic.h:121
void nmg_s_to_vlist(struct bu_list *vhead, const struct shell *s, int poly_markers)
Definition: nmg_plot.c:347
void nmg_offset_eu_vert(fastf_t *base, const struct edgeuse *eu, const fastf_t *face_normal, int tip)
Definition: nmg_plot.c:449
#define BN_VLIST_POLY_VERTNORM
per-vertex normal, for interpolation
Definition: vlist.h:88
#define BN_VLIST_POLY_END
last vert (repeats 1st), draw poly
Definition: vlist.h:87
#define NMG_VERTEXUSE_A_PLANE_MAGIC
Definition: magic.h:144
void rt_nurb_s_eval(const struct face_g_snurb *srf, fastf_t u, fastf_t v, fastf_t *final_value)
Definition: nurb_eval.c:49
void pdv_3point(register FILE *plotfp, const fastf_t *pt)
Definition: plot3.c:606
ustring label
void nmg_snurb_fu_eval(const struct faceuse *fu, const fastf_t u, const fastf_t v, fastf_t *pt_on_srf)
Definition: nmg_misc.c:160
Definition: color.c:51
#define PICK_BROKEN_COLOR(p)
Definition: nmg_plot.c:1456
double bn_angle_measure(vect_t vec, const vect_t x_dir, const vect_t y_dir)
void nmg_snurb_fu_to_vlist(struct bu_list *vhead, const struct faceuse *fu, int poly_markers)
Definition: nmg_plot.c:297
double nmg_eue_dist
Definition: globals.c:49
void rt_nurb_kvgen(register struct knot_vector *kv, fastf_t lower, fastf_t upper, int num, struct resource *res)
Definition: nurb_knot.c:121
void bu_free(void *ptr, const char *str)
Definition: malloc.c:328
#define BU_CK_LIST_HEAD(_p)
Definition: list.h:142
void rt_nurb_c_eval(const struct edge_g_cnurb *crv, fastf_t param, fastf_t *final_value)
Definition: nurb_eval.c:125
NMG_CK_SHELL(s)
void nmg_vu_to_vlist(struct bu_list *vhead, const struct vertexuse *vu)
Definition: nmg_plot.c:71
#define NMG_FACEUSE_MAGIC
Definition: magic.h:124
int nmg_snurb_to_vlist(struct bu_list *vhead, const struct face_g_snurb *fg, int n_interior)
Definition: nmg_plot.c:2164
void bu_bomb(const char *str) _BU_ATTR_NORETURN
Definition: bomb.c:91
void nmg_pl_edges_in_2_shells(struct bn_vlblock *vbp, long *b, const struct edgeuse *eu, int fancy, const struct bn_tol *tol)
Definition: nmg_plot.c:1224
HIDDEN void show_broken_e(struct bn_vlblock *vbp, const struct edgeuse *eu)
Definition: nmg_plot.c:1525
double fastf_t
Definition: defines.h:300
void nmg_vlblock_fu(struct bn_vlblock *vbp, const struct faceuse *fu, long *tab, int fancy)
Definition: nmg_plot.c:1113
void nmg_pl_2fu(const char *str, const struct faceuse *fu1, const struct faceuse *fu2, int show_mates)
Definition: nmg_plot.c:1380
void rt_plot_vlblock(FILE *fp, const struct bn_vlblock *vbp)
Definition: vlist.c:427
Definition: color.c:50
void nmg_plot_ray_face(const char *fname, fastf_t *pt, const fastf_t *dir, const struct faceuse *fu)
Definition: nmg_plot.c:2072
#define BU_LIST_FIRST(structure, hp)
Definition: list.h:312
void(* nmg_vlblock_anim_upcall)(void)
Definition: globals.c:45
void nmg_pl_e(FILE *fp, const struct edge *e, long *b, int red, int green, int blue)
Definition: nmg_plot.c:622
struct rt_g RTG
Definition: globals.c:39
struct model * nmg_find_model(const uint32_t *magic_p_arg)
Definition: nmg_info.c:57