BRL-CAD
nmg_mesh.c
Go to the documentation of this file.
1 /* N M G _ M E S H . C
2  * BRL-CAD
3  *
4  * Copyright (c) 1989-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_mesh.c
23  *
24  * Meshing routines for n-Manifold Geometry.
25  * This stuff is destined to be absorbed into nmg_fuse.c.
26  * "meshing" here refers to the sorting of faceuses around an edge
27  * as two edges sharing the same end points (vertex structs) are fused.
28  *
29  */
30 /** @} */
31 
32 #include "common.h"
33 
34 #include <math.h>
35 #include "bio.h"
36 
37 #include "vmath.h"
38 #include "nmg.h"
39 #include "raytrace.h"
40 
41 
42 /**
43  * Determine if T lies within angle AB, such that A < T < B.
44  * The angle B is expected to be "more ccw" than A.
45  * Because of the wrap from 2pi to 0, B may have a smaller numeric value.
46  *
47  * Returns -
48  * -2 t is equal to a
49  * -1 t is equal to b
50  * 0 t is outside angle ab
51  * 1 t is inside angle ab
52  */
53 int
54 nmg_is_angle_in_wedge(double a, double b, double t)
55 {
56  /* XXX What tolerance to use here (in radians)? */
57  if (NEAR_EQUAL(a, t, 1.0e-8)) return -2;
58  if (NEAR_EQUAL(b, t, 1.0e-8)) return -1;
59 
60  /* If A==B, if T is not also equal, it's outside the wedge */
61  if (NEAR_EQUAL(a, b, 1.0e-8)) return 0;
62 
63  if (b < a) {
64  /* B angle has wrapped past zero, add on 2pi */
65  if (t <= b) {
66  /* Range is A..0, 0..B, and 0<t<B; so T is in wedge */
67  return 1;
68  }
69  b += M_2PI;
70  }
71  if (NEAR_EQUAL(b, t, 1.0e-8)) return -1;
72 
73  if (t < a) return 0;
74  if (t > b) return 0;
75  return 1;
76 }
77 
78 
79 /**
80  * Given two edgeuses with different edge geometry but
81  * running between the same two vertices,
82  * select the proper edge geometry to associate with.
83  *
84  * Really, there are 3 geometries to be compared here:
85  * the vector between the two endpoints of this edge,
86  * and the two edge_g structures.
87  * Rather than always taking eu2 or eu1,
88  * select the one that best fits this one edge.
89  *
90  * Consider fu1:
91  * B
92  * *
93  * /|
94  * eg2/ |
95  * / |
96  * D/ |
97  * * |
98  * / |
99  * A *-*----* C
100  * E eg1
101  *
102  * At the start of a face/face intersection, eg1 runs from A to C,
103  * and eg2 runs ADB. The line of intersection with the other face
104  * (fu2, not drawn) lies along eg1.
105  * Assume that edge AC needs to be broken at E,
106  * where E is just a little more than tol->dist away from A.
107  * Existing point D is found because it *is* within tol->dist of E,
108  * thanks to the cosine of angle BAC.
109  * So, edge AC is broken on vertex D, and the intersection list
110  * contains vertexuses A, E, and C.
111  *
112  * Because D and E are the same point, fu1 has become a triangle with
113  * a little "spike" on the end. If this is handled simply by re-homing
114  * edge AE to eg2, it may cause trouble, because eg1 now runs EC,
115  * but the geometry for eg1 runs AC. If there are other vertices on
116  * edge eg1, the problem can not be resolved simply by recomputing the
117  * geometry of eg1.
118  * Since E (D) is within tolerance of eg1, it is not unreasonable
119  * just to leave eg1 alone.
120  *
121  * The issue boils down to selecting whether the existing eg1 or eg2
122  * best represents the direction of the little stub edge AD (shared with AE).
123  * In this case, eg2 is the correct choice, as AD (and AE) lie on line AB.
124  *
125  * It would be disastrous to force *all* of eg1 to use the edge geometry
126  * of eg2, as the two lines are very different.
127  */
128 struct edge_g_lseg *
129 nmg_pick_best_edge_g(struct edgeuse *eu1, struct edgeuse *eu2, const struct bn_tol *tol)
130 {
131  NMG_CK_EDGEUSE(eu1);
132  NMG_CK_EDGEUSE(eu2);
133  BN_CK_TOL(tol);
134 
135  NMG_CK_EDGE_G_LSEG(eu1->g.lseg_p);
136  NMG_CK_EDGE_G_LSEG(eu2->g.lseg_p);
137  if (eu2->g.lseg_p != eu1->g.lseg_p) {
138  vect_t dir;
139  vect_t dir_2;
140  vect_t dir_1;
141  fastf_t dot_2;
142  fastf_t dot_1;
143 
144  VSUB2(dir, eu1->vu_p->v_p->vg_p->coord, eu1->eumate_p->vu_p->v_p->vg_p->coord);
145  VUNITIZE(dir);
146  VMOVE(dir_2, eu2->g.lseg_p->e_dir);
147  VUNITIZE(dir_2);
148  VMOVE(dir_1, eu1->g.lseg_p->e_dir);
149  VUNITIZE(dir_1);
150 
151  dot_2 = fabs(VDOT(dir, dir_2));
152  dot_1 = fabs(VDOT(dir, dir_1));
153 
154  /* Dot product of 1 means colinear. Take largest dot. */
155  if (dot_2 > dot_1) {
156  if (RTG.NMG_debug & DEBUG_BASIC) {
157  bu_log("nmg_pick_best_edge_g() Make eu1 use geometry of eu2, s.d=%g, d.d=%g\n",
158  acos(dot_2)*RAD2DEG,
159  acos(dot_1)*RAD2DEG);
160  }
161  return eu2->g.lseg_p;
162  } else {
163  if (RTG.NMG_debug & DEBUG_BASIC) {
164  bu_log("nmg_pick_best_edge_g() Make eu2 use geometry of eu1, s.d=%g, d.d=%g\n",
165  acos(dot_2)*RAD2DEG,
166  acos(dot_1)*RAD2DEG);
167  }
168  return eu1->g.lseg_p;
169  }
170  }
171  return eu1->g.lseg_p; /* both the same */
172 }
173 
174 
175 /**
176  * Make all the edgeuses around eu2's edge to refer to eu1's edge,
177  * taking care to organize them into the proper angular orientation,
178  * so that the attached faces are correctly arranged radially
179  * around the edge.
180  *
181  * This depends on both edges being part of face loops,
182  * with vertex and face geometry already associated.
183  *
184  * The two edgeuses being joined might well be from separate shells,
185  * so the issue of preserving (simple) faceuse orientation parity
186  * (SAME, OPPOSITE, OPPOSITE, SAME, ...)
187  * can't be used here -- that only applies to faceuses from the same shell.
188  *
189  * Some of the edgeuses around both edges may be wires.
190  *
191  * Call to nmg_check_radial at end has been deleted.
192  * Note that after two radial EU's have been joined
193  * a third cannot be joined to them without creating
194  * unclosed space that nmg_check_radial will find.
195  */
196 void
197 nmg_radial_join_eu(struct edgeuse *eu1, struct edgeuse *eu2, const struct bn_tol *tol)
198 {
199 
200  NMG_CK_EDGEUSE(eu1);
201  NMG_CK_EDGEUSE(eu1->radial_p);
202  NMG_CK_EDGEUSE(eu1->eumate_p);
203  NMG_CK_EDGEUSE(eu2);
204  NMG_CK_EDGEUSE(eu2->radial_p);
205  NMG_CK_EDGEUSE(eu2->eumate_p);
206  BN_CK_TOL(tol);
207 
208  if (eu1->e_p == eu2->e_p) return;
209 
210  if (!NMG_ARE_EUS_ADJACENT(eu1, eu2))
211  bu_bomb("nmg_radial_join_eu() edgeuses don't share vertices.\n");
212 
213  if (eu1->vu_p->v_p == eu1->eumate_p->vu_p->v_p) bu_bomb("nmg_radial_join_eu(): 0 length edge (topology)\n");
214 
215  if (bn_pt3_pt3_equal(eu1->vu_p->v_p->vg_p->coord,
216  eu1->eumate_p->vu_p->v_p->vg_p->coord, tol))
217  {
218  bu_log("vertices should have been fused:\n");
219  bu_log("\tvertex %p (%.12f %.12f %.12f)\n",
220  (void *)eu1->vu_p->v_p,
221  V3ARGS(eu1->vu_p->v_p->vg_p->coord));
222  bu_log("\tvertex %p (%.12f %.12f %.12f)\n",
223  (void *)eu1->eumate_p->vu_p->v_p,
224  V3ARGS(eu1->eumate_p->vu_p->v_p->vg_p->coord));
225  bu_bomb("nmg_radial_join_eu(): 0 length edge (geometry)\n");
226  }
227 
228 #if 1
229  nmg_radial_join_eu_NEW(eu1, eu2, tol);
230  return;
231 #else
232 
233  /* Ensure faces are of same orientation, if both eu's have faces */
234  fu1 = nmg_find_fu_of_eu(eu1);
235  fu2 = nmg_find_fu_of_eu(eu2);
236  if (fu1 && fu2) {
237  if (fu1->orientation != fu2->orientation) {
238  eu2 = eu2->eumate_p;
239  fu2 = nmg_find_fu_of_eu(eu2);
240  if (fu1->orientation != fu2->orientation)
241  bu_bomb("nmg_radial_join_eu(): Cannot find matching orientations for faceuses\n");
242  }
243  }
244 
245  /* XXX This angle-based algorithm can't handle snurb faces! */
246  if (fu1 && fu1->f_p->g.magic_p && *fu1->f_p->g.magic_p == NMG_FACE_G_SNURB_MAGIC) return;
247  if (fu2 && fu2->f_p->g.magic_p && *fu2->f_p->g.magic_p == NMG_FACE_G_SNURB_MAGIC) return;
248 
249  /* Construct local coordinate system for this edge,
250  * so all angles can be measured relative to a common reference.
251  */
252  nmg_eu_2vecs_perp(xvec, yvec, zvec, original_eu1, tol);
253 
254  if (RTG.NMG_debug & DEBUG_MESH_EU) {
255  bu_log("nmg_radial_join_eu(eu1=%p, eu2=%p) e1=%p, e2=%p\n",
256  (void *)eu1, (void *)eu2,
257  (void *)eu1->e_p, (void *)eu2->e_p);
258  nmg_euprint("\tJoining", eu1);
259  nmg_euprint("\t to", eu2);
260  bu_log("Faces around eu1:\n");
261  nmg_pr_fu_around_eu_vecs(eu1, xvec, yvec, zvec, tol);
262  bu_log("Faces around eu2:\n");
263  nmg_pr_fu_around_eu_vecs(eu2, xvec, yvec, zvec, tol);
264  }
265 
266  best_eg = nmg_pick_best_edge_g(eu1, eu2, tol);
267 
268  for (iteration1=0; eu2 && iteration1 < 10000; iteration1++) {
269  int code = 0;
270  struct edgeuse *first_eu1 = eu1;
271  int wire_skip = 0;
272  /* Resume where we left off from last eu2 insertion */
273 
274  /* find a place to insert eu2 around eu1's edge */
275  for (iteration2=0; iteration2 < 10000; iteration2++) {
276  struct faceuse *fur;
277 
278  abs1 = abs2 = absr = -M_2PI;
279 
280  eur = eu1->radial_p;
281  NMG_CK_EDGEUSE(eur);
282 
283  fu2 = nmg_find_fu_of_eu(eu2);
284  if (fu2 == (struct faceuse *)NULL) {
285  /* eu2 is a wire, it can go anywhere */
286  bu_log("eu2=%p is a wire, insert after eu1=%p\n", (void *)eu2, (void *)eu1);
287  goto insert;
288  }
289  fu1 = nmg_find_fu_of_eu(eu1);
290  if (fu1 == (struct faceuse *)NULL) {
291  /* eu1 is a wire, skip on to real face eu */
292  bu_log("eu1=%p is a wire, skipping on\n", (void *)eu1);
293  wire_skip++;
294  goto cont;
295  }
296  fur = nmg_find_fu_of_eu(eur);
297  while (fur == (struct faceuse *)NULL) {
298  /* eur is wire, advance eur */
299  bu_log("eur=%p is a wire, advancing to non-wire eur\n", (void *)eur);
300  eur = eur->eumate_p->radial_p;
301  wire_skip++;
302  if (eur == eu1->eumate_p) {
303  bu_log("went all the way around\n");
304  /* Went all the way around */
305  goto insert;
306  }
307  fur = nmg_find_fu_of_eu(eur);
308  }
309  NMG_CK_FACEUSE(fu1);
310  NMG_CK_FACEUSE(fu2);
311  NMG_CK_FACEUSE(fur);
312 
313  /*
314  * Can't just check for shared fg here,
315  * the angle changes by +/- 180 degrees,
316  * depending on which side of the eu the loop is on
317  * along this edge.
318  */
319  abs1 = nmg_measure_fu_angle(eu1, xvec, yvec, zvec);
320  abs2 = nmg_measure_fu_angle(eu2, xvec, yvec, zvec);
321  absr = nmg_measure_fu_angle(eur, xvec, yvec, zvec);
322 
323  if (RTG.NMG_debug & DEBUG_MESH_EU) {
324  bu_log(" abs1=%g, abs2=%g, absr=%g\n",
325  abs1*RAD2DEG,
326  abs2*RAD2DEG,
327  absr*RAD2DEG);
328  }
329 
330  /* If abs1 == absr, warn about unfused faces, and skip. */
331  if (NEAR_EQUAL(abs1, absr, 1.0e-8)) {
332  if (fu1->f_p->g.plane_p == fur->f_p->g.plane_p) {
333  /* abs1 == absr, faces are fused, don't insert here. */
334  if (RTG.NMG_debug & DEBUG_MESH_EU) {
335  bu_log("fu1 and fur share face geometry %p (flip1=%d, flip2=%d), skip\n",
336  (void *)fu1->f_p->g.plane_p, fu1->f_p->flip, fur->f_p->flip);
337  }
338  goto cont;
339  }
340 
341  bu_log("nmg_radial_join_eu: WARNING 2 faces should have been fused, may be ambiguous.\n abs1=%e, absr=%e, asb2=%e\n",
342  abs1*RAD2DEG, absr*RAD2DEG, abs2*RAD2DEG);
343  bu_log(" fu1=%p, f1=%p, f1->flip=%d, fg1=%p\n",
344  (void *)fu1, (void *)fu1->f_p, fu1->f_p->flip, (void *)fu1->f_p->g.plane_p);
345  bu_log(" fu2=%p, f2=%p, f2->flip=%d, fg2=%p\n",
346  (void *)fu2, (void *)fu2->f_p, fu2->f_p->flip, (void *)fu2->f_p->g.plane_p);
347  bu_log(" fur=%p, fr=%p, fr->flip=%d, fgr=%p\n",
348  (void *)fur, (void *)fur->f_p, fur->f_p->flip, (void *)fur->f_p->g.plane_p);
349  PLPRINT(" fu1", fu1->f_p->g.plane_p->N);
350  PLPRINT(" fu2", fu2->f_p->g.plane_p->N);
351  PLPRINT(" fur", fur->f_p->g.plane_p->N);
352  {
353  int debug = RTG.NMG_debug;
354 
355  if (nmg_two_face_fuse(fu1->f_p, fur->f_p, tol) == 0)
356  bu_bomb("faces didn't fuse?\n");
357  RTG.NMG_debug = debug;
358  }
359  bu_log(" nmg_radial_join_eu() skipping this eu\n");
360  goto cont;
361  }
362 
363  /*
364  * If abs1 < abs2 < absr
365  * (taking into account 360 wrap),
366  * then insert face here.
367  * Special handling if abs1==abs2 or abs2==absr.
368  */
369  code = nmg_is_angle_in_wedge(abs1, absr, abs2);
370  if (RTG.NMG_debug & DEBUG_MESH_EU)
371  bu_log(" code=%d %s\n", code, (code!=0)?"INSERT_HERE":"skip");
372  if (code > 0) break;
373  if (code == -1) {
374  /* absr == abs2 */
375  break;
376  }
377  if (code <= -2) {
378  /* abs1 == abs2 */
379  break;
380  }
381 
382  cont:
383  /* If eu1 is only one pair of edgeuses, done */
384  if (eu1 == eur->eumate_p) break;
385  eu1 = eur->eumate_p;
386  if (eu1 == first_eu1) {
387  /* If all eu's were wires, here is fine */
388  if (wire_skip >= iteration2) break;
389  /* Nope, something bad happened */
390  bu_bomb("nmg_radial_join_eu(): went full circle, no face insertion point.\n");
391  break;
392  }
393  }
394  if (iteration2 >= 10000) {
395  bu_bomb("nmg_radial_join_eu: infinite loop (2)\n");
396  }
397 
398  /* find the next use of the edge eu2 is on. If eu2 and its
399  * mate are the last uses of the edge, there will be no next
400  * edgeuse to move. (Loop termination condition).
401  */
402  insert:
403  nexteu = eu2->radial_p;
404  if (nexteu == eu2->eumate_p)
405  nexteu = (struct edgeuse *)NULL;
406 
407  /* because faces are always created with counter-clockwise
408  * exterior loops and clockwise interior loops,
409  * radial edgeuses IN THE SAME SHELL will never point in
410  * the same direction or share the same vertex. We thus make
411  * sure that eu2 is an edgeuse which might be radial to eu1
412  * XXX Need to look back for last eu IN THE SHELL OF eu2.
413  * XXX Even this isn't good enough, as we may be inserting
414  * XXX something new _after_ that last starting point.
415  */
416  eus = eu1;
417  while (nmg_find_s_of_eu(eus) != nmg_find_s_of_eu(eu2)) {
418  eus = eus->eumate_p->radial_p;
419  if (eus == eu1) break; /* full circle */
420  }
421 
422  if (eu2->vu_p->v_p == eus->vu_p->v_p)
423  eu2 = eu2->eumate_p;
424 
425  if (RTG.NMG_debug & DEBUG_MESH_EU) {
426  bu_log(" Inserting. code=%d\n", code);
427  bu_log("joining eu1=%p eu2=%p with abs1=%g, absr=%g\n",
428  (void *)eu1, (void *)eu2,
429  abs1*RAD2DEG, absr*RAD2DEG);
430  }
431 
432  /*
433  * Make eu2 radial to eu1.
434  * This should insert eu2 between eu1 and eu1->radial_p
435  * (which may be less far around than eur, but that's OK).
436  * This does NOT change the edge geometry pointer.
437  */
438  nmg_je(eu1, eu2);
439 
440  if (RTG.NMG_debug & DEBUG_MESH_EU) {
441  bu_log("After nmg_je(), faces around original_eu1 are:\n");
442  nmg_pr_fu_around_eu_vecs(original_eu1, xvec, yvec, zvec, tol);
443  }
444 
445  /* Proceed to the next source edgeuse */
446  eu2 = nexteu;
447  }
448  if (iteration1 >= 10000) bu_bomb("nmg_radial_join_eu: infinite loop (1)\n");
449 
450  NMG_CK_EDGEUSE(original_eu1);
451 
452  /*
453  * Make another pass, ensuring that all edgeuses are using the
454  * "best_eg" line.
455  */
456  eu1 = original_eu1;
457  for (;;) {
458  if (eu1->g.lseg_p != best_eg) {
459  nmg_use_edge_g(eu1, &best_eg->l.magic);
460  }
461 
462  eu1 = eu1->eumate_p->radial_p;
463  if (eu1 == original_eu1) break;
464  }
465 
466  if (RTG.NMG_debug & DEBUG_MESH_EU) bu_log("nmg_radial_join_eu: END\n");
467 #endif
468 }
469 
470 
471 /**
472  * Actually do the work of meshing two faces.
473  * The two fu arguments may be the same, which causes the face to be
474  * meshed against itself.
475  *
476  * The return is the number of edges meshed.
477  */
478 int
479 nmg_mesh_two_faces(register struct faceuse *fu1, register struct faceuse *fu2, const struct bn_tol *tol)
480 {
481  struct loopuse *lu1;
482  struct loopuse *lu2;
483  struct edgeuse *eu1;
484  struct edgeuse *eu2;
485  struct vertex *v1a, *v1b;
486  struct edge *e1;
487  pointp_t pt1, pt2;
488  int count = 0;
489 
490  /* Visit all the loopuses in faceuse 1 */
491  for (BU_LIST_FOR(lu1, loopuse, &fu1->lu_hd)) {
492  /* Ignore self-loops */
493  if (BU_LIST_FIRST_MAGIC(&lu1->down_hd) != NMG_EDGEUSE_MAGIC)
494  continue;
495 
496  /* Visit all the edgeuses in loopuse1 */
497  for (BU_LIST_FOR(eu1, edgeuse, &lu1->down_hd)) {
498 
499  v1a = eu1->vu_p->v_p;
500  v1b = eu1->eumate_p->vu_p->v_p;
501  e1 = eu1->e_p;
502  if (RTG.NMG_debug & DEBUG_MESH) {
503  pt1 = v1a->vg_p->coord;
504  pt2 = v1b->vg_p->coord;
505  bu_log("ref_e=%8p v:%8p--%8p (%g, %g, %g)->(%g, %g, %g)\n",
506  (void *)e1, (void *)v1a, (void *)v1b,
507  V3ARGS(pt1), V3ARGS(pt2));
508  }
509 
510  /* Visit all the loopuses in faceuse2 */
511  for (BU_LIST_FOR(lu2, loopuse, &fu2->lu_hd)) {
512  /* Ignore self-loops */
513  if (BU_LIST_FIRST_MAGIC(&lu2->down_hd) != NMG_EDGEUSE_MAGIC)
514  continue;
515  /* Visit all the edgeuses in loopuse2 */
516  for (BU_LIST_FOR(eu2, edgeuse, &lu2->down_hd)) {
517  if (RTG.NMG_debug & DEBUG_MESH) {
518  pt1 = eu2->vu_p->v_p->vg_p->coord;
519  pt2 = eu2->eumate_p->vu_p->v_p->vg_p->coord;
520  bu_log("\te:%8p v:%8p--%8p (%g, %g, %g)->(%g, %g, %g)\n",
521  (void *)eu2->e_p,
522  (void *)eu2->vu_p->v_p,
523  (void *)eu2->eumate_p->vu_p->v_p,
524  V3ARGS(pt1), V3ARGS(pt2));
525  }
526 
527  /* See if already shared */
528  if (eu2->e_p == e1) continue;
529  if ((eu2->vu_p->v_p == v1a &&
530  eu2->eumate_p->vu_p->v_p == v1b) ||
531  (eu2->eumate_p->vu_p->v_p == v1a &&
532  eu2->vu_p->v_p == v1b)) {
533  nmg_radial_join_eu(eu1, eu2, tol);
534  count++;
535  }
536  }
537  }
538  }
539  }
540  return count;
541 }
542 
543 
544 /**
545  * Scan through all the edges of fu1 and fu2, ensuring that all
546  * edges involving the same vertex pair are indeed shared.
547  * This means worrying about merging ("meshing") all the faces in the
548  * proper radial orientation around the edge.
549  * XXX probably should return count;
550  */
551 void
552 nmg_mesh_faces(struct faceuse *fu1, struct faceuse *fu2, const struct bn_tol *tol)
553 {
554  int count = 0;
555 
556  NMG_CK_FACEUSE(fu1);
557  NMG_CK_FACEUSE(fu2);
558  BN_CK_TOL(tol);
559 
560  if (RTG.NMG_debug & DEBUG_MESH_EU && RTG.NMG_debug & DEBUG_PLOTEM) {
561  nmg_pl_2fu("Before_mesh%d.plot3", fu1, fu2, 1);
562  }
563 
564  if (RTG.NMG_debug & DEBUG_MESH_EU)
565  bu_log("meshing self (fu1 %8p)\n", (void *)fu1);
566  count += nmg_mesh_two_faces(fu1, fu1, tol);
567 
568  if (RTG.NMG_debug & DEBUG_MESH_EU)
569  bu_log("meshing self (fu2 %8p)\n", (void *)fu2);
570  count += nmg_mesh_two_faces(fu2, fu2, tol);
571 
572  if (RTG.NMG_debug & DEBUG_MESH_EU)
573  bu_log("meshing to other (fu1:%8p fu2:%8p)\n", (void *)fu1, (void *)fu2);
574  count += nmg_mesh_two_faces(fu1, fu2, tol);
575 
576  if (RTG.NMG_debug & DEBUG_MESH_EU && RTG.NMG_debug & DEBUG_PLOTEM) {
577  nmg_pl_2fu("After_mesh%d.plot3", fu1, fu2, 1);
578  }
579 }
580 
581 
582 /**
583  * The return is the number of edges meshed.
584  */
585 int
586 nmg_mesh_face_shell(struct faceuse *fu1, struct shell *s, const struct bn_tol *tol)
587 {
588  register struct faceuse *fu2;
589  int count = 0;
590 
591  NMG_CK_FACEUSE(fu1);
592  NMG_CK_SHELL(s);
593  BN_CK_TOL(tol);
594 
595  count += nmg_mesh_two_faces(fu1, fu1, tol);
596  for (BU_LIST_FOR(fu2, faceuse, &s->fu_hd)) {
597  NMG_CK_FACEUSE(fu2);
598  count += nmg_mesh_two_faces(fu2, fu2, tol);
599  count += nmg_mesh_two_faces(fu1, fu2, tol);
600  }
601  /* XXX What about wire edges in the shell? */
602  return count;
603 }
604 
605 
606 /**
607  * Mesh every edge in shell 1 with every edge in shell 2.
608  * The return is the number of edges meshed.
609  *
610  * Does not use nmg_mesh_face_shell() to keep face/self meshing
611  * to the absolute minimum necessary.
612  */
613 int
614 nmg_mesh_shell_shell(struct shell *s1, struct shell *s2, const struct bn_tol *tol)
615 {
616  struct faceuse *fu1;
617  struct faceuse *fu2;
618  int count = 0;
619 
620  NMG_CK_SHELL(s1);
621  NMG_CK_SHELL(s2);
622  BN_CK_TOL(tol);
623 
624  nmg_region_v_unique(s1->r_p, tol);
625  nmg_region_v_unique(s2->r_p, tol);
626 
627  /* First, mesh all faces of shell 2 with themselves */
628  for (BU_LIST_FOR(fu2, faceuse, &s2->fu_hd)) {
629  NMG_CK_FACEUSE(fu2);
630  count += nmg_mesh_two_faces(fu2, fu2, tol);
631  }
632 
633  /* Visit every face in shell 1 */
634  for (BU_LIST_FOR(fu1, faceuse, &s1->fu_hd)) {
635  NMG_CK_FACEUSE(fu1);
636 
637  /* First, mesh each face in shell 1 with itself */
638  count += nmg_mesh_two_faces(fu1, fu1, tol);
639 
640  /* Visit every face in shell 2 */
641  for (BU_LIST_FOR(fu2, faceuse, &s2->fu_hd)) {
642  NMG_CK_FACEUSE(fu2);
643  count += nmg_mesh_two_faces(fu1, fu2, tol);
644  }
645  }
646 
647  /* XXX What about wire edges in the shell? */
648 
649  /* Visit every wire loop in shell 1 */
650 
651  /* Visit every wire edge in shell 1 */
652 
653  return count;
654 }
655 
656 
657 /*
658  * Local Variables:
659  * mode: C
660  * tab-width: 8
661  * indent-tabs-mode: t
662  * c-file-style: "stroustrup"
663  * End:
664  * ex: shiftwidth=4 tabstop=8
665  */
int nmg_is_angle_in_wedge(double a, double b, double t)
Definition: nmg_mesh.c:54
#define BU_LIST_FOR(p, structure, hp)
Definition: list.h:365
#define NMG_EDGEUSE_MAGIC
Definition: magic.h:120
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 nmg_radial_join_eu(struct edgeuse *eu1, struct edgeuse *eu2, const struct bn_tol *tol)
Definition: nmg_mesh.c:197
void nmg_euprint(const char *str, const struct edgeuse *eu)
Definition: nmg_pr.c:751
#define NMG_FACE_G_SNURB_MAGIC
Definition: magic.h:126
void nmg_je(struct edgeuse *eudst, struct edgeuse *eusrc)
Definition: nmg_mk.c:2765
if lu s
Definition: nmg_mod.c:3860
Header file for the BRL-CAD common definitions.
BU_LIST_DEQUEUE & eu1
Definition: nmg_mod.c:3839
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
int nmg_use_edge_g(struct edgeuse *eu, uint32_t *magic_p)
Definition: nmg_mk.c:2087
int nmg_two_face_fuse(struct face *f1, struct face *f2, const struct bn_tol *tol)
Definition: nmg_fuse.c:1571
uint32_t NMG_debug
debug bits for NMG's see nmg.h
Definition: raytrace.h:1699
struct edge_g_lseg * nmg_pick_best_edge_g(struct edgeuse *eu1, struct edgeuse *eu2, const struct bn_tol *tol)
Definition: nmg_mesh.c:129
#define V3ARGS(a)
Definition: color.c:56
int nmg_mesh_face_shell(struct faceuse *fu1, struct shell *s, const struct bn_tol *tol)
Definition: nmg_mesh.c:586
void nmg_pr_fu_around_eu_vecs(const struct edgeuse *eu, const fastf_t *xvec, const fastf_t *yvec, const fastf_t *zvec, const struct bn_tol *tol)
Definition: nmg_pr.c:918
int nmg_mesh_shell_shell(struct shell *s1, struct shell *s2, const struct bn_tol *tol)
Definition: nmg_mesh.c:614
double nmg_measure_fu_angle(const struct edgeuse *eu, const fastf_t *xvec, const fastf_t *yvec, const fastf_t *zvec)
Definition: nmg_info.c:391
Support for uniform tolerances.
Definition: tol.h:71
struct shell * nmg_find_s_of_eu(const struct edgeuse *eu)
Definition: nmg_info.c:235
#define BN_CK_TOL(_p)
Definition: tol.h:82
#define BU_LIST_FIRST_MAGIC(hp)
Definition: list.h:416
int nmg_mesh_two_faces(register struct faceuse *fu1, register struct faceuse *fu2, const struct bn_tol *tol)
Definition: nmg_mesh.c:479
HIDDEN int code(fastf_t x, fastf_t y)
Definition: clip.c:43
void nmg_mesh_faces(struct faceuse *fu1, struct faceuse *fu2, const struct bn_tol *tol)
Definition: nmg_mesh.c:552
void nmg_region_v_unique(struct nmgregion *r1, const struct bn_tol *tol)
Definition: nmg_fuse.c:127
void nmg_radial_join_eu_NEW(struct edgeuse *eu1, struct edgeuse *eu2, const struct bn_tol *tol)
Definition: nmg_fuse.c:3197
NMG_CK_SHELL(s)
int bn_pt3_pt3_equal(const point_t a, const point_t b, const struct bn_tol *tol)
void bu_bomb(const char *str) _BU_ATTR_NORETURN
Definition: bomb.c:91
double fastf_t
Definition: defines.h:300
eu2
Definition: nmg_mod.c:3875
void nmg_pl_2fu(const char *str, const struct faceuse *fu1, const struct faceuse *fu2, int show_mates)
Definition: nmg_plot.c:1380
struct rt_g RTG
Definition: globals.c:39