BRL-CAD
edge.h
Go to the documentation of this file.
1 /* E D G E . H
2  * BRL-CAD
3  *
4  * Copyright (c) 2004-2024 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 
21 /*----------------------------------------------------------------------*/
22 /** @addtogroup nmg_edge */
23 /** @{ */
24 /** @file nmg/edge.h */
25 
26 #ifndef NMG_EDGE_H
27 #define NMG_EDGE_H
28 
29 #include "common.h"
30 
31 #include "vmath.h"
32 #include "bu/list.h"
33 #include "nmg/defines.h"
34 #include "nmg/topology.h"
35 
36 __BEGIN_DECLS
37 
38 #define NMG_CK_EDGE(_p) NMG_CKMAG(_p, NMG_EDGE_MAGIC, "edge")
39 #define NMG_CK_EDGE_G_LSEG(_p) NMG_CKMAG(_p, NMG_EDGE_G_LSEG_MAGIC, "edge_g_lseg")
40 #define NMG_CK_EDGEUSE(_p) NMG_CKMAG(_p, NMG_EDGEUSE_MAGIC, "edgeuse")
41 
42 #define GET_EDGE(p, m) {NMG_GETSTRUCT(p, edge); NMG_INCR_INDEX(p, m);}
43 #define GET_EDGE_G_LSEG(p, m) {NMG_GETSTRUCT(p, edge_g_lseg); NMG_INCR_INDEX(p, m);}
44 #define GET_EDGE_G_CNURB(p, m) {NMG_GETSTRUCT(p, edge_g_cnurb); NMG_INCR_INDEX(p, m);}
45 #define GET_EDGEUSE(p, m) {NMG_GETSTRUCT(p, edgeuse); NMG_INCR_INDEX(p, m);}
46 
47 #define FREE_EDGE(p) NMG_FREESTRUCT(p, edge)
48 #define FREE_EDGE_G_LSEG(p) NMG_FREESTRUCT(p, edge_g_lseg)
49 #define FREE_EDGE_G_CNURB(p) NMG_FREESTRUCT(p, edge_g_cnurb)
50 #define FREE_EDGEUSE(p) NMG_FREESTRUCT(p, edgeuse)
51 
52 /**
53  * @brief Compute the equation of the line formed by the endpoints of the
54  * edge.
55  */
56 NMG_EXPORT extern void nmg_edge_g(struct edgeuse *eu);
57 
58 /**
59  * @brief Associate edgeuse 'eu' with the edge geometry structure identified by
60  * 'magic_p', where magic_p is the pointer to the magic entry of an edge_g_lseg.
61  *
62  * Example magic_p keys: eu->g.magic_p &eg->l.magic
63  *
64  * If the edgeuse is already associated with some geometry, that geometry is
65  * first released. Note that, to start with, the two edgeuses may be using
66  * different original geometries.
67  *
68  * Also do the edgeuse mate.
69  *
70  * @retval 0 If the old edge geometry (eu->g.magic_p) has other uses.
71  * @retval 1 If the old edge geometry has been destroyed. Caller beware!
72  */
73 NMG_EXPORT extern int nmg_use_edge_g(struct edgeuse *eu,
74  uint32_t *magic_p);
75 
76 /**
77  * @brief Demote a wire edge into a pair of self-loop vertices
78  *
79  * @retval 0 If all is well
80  * @retval 1 If shell is empty, and is thus "illegal".
81  */
82 NMG_EXPORT extern int nmg_demote_eu(struct edgeuse *eu);
83 
84 /**
85  * @brief Move a pair of edgeuses onto a single edge (glue edgeuse).
86  *
87  * The edgeuse eusrc and its mate are moved to the edge used by eudst. eusrc
88  * is made to be immediately radial to eudst. If eusrc does not share the same
89  * vertices as eudst, we bomb.
90  *
91  * The edgeuse geometry pointers are not changed by this operation.
92  *
93  * This routine was formerly called nmg_moveeu().
94  */
95 NMG_EXPORT extern void nmg_je(struct edgeuse *eudst,
96  struct edgeuse *eusrc);
97 
98 /**
99  * @brief If edgeuse is part of a shared edge (more than one pair of edgeuses
100  * on the edge), it and its mate are "unglued" from the edge, and associated
101  * with a new edge structure.
102  *
103  * Primarily a support routine for nmg_eusplit()
104  *
105  * If the original edge had edge geometry, that is *not* duplicated here,
106  * because it is not easy (or appropriate) for nmg_eusplit() to know whether
107  * the new vertex lies on the previous edge geometry or not. Hence having the
108  * nmg_ebreak() interface, which preserves the edge geometry across a split, and
109  * nmg_esplit() which does not.
110  */
111 NMG_EXPORT extern void nmg_unglueedge(struct edgeuse *eu);
112 
113 /**
114  * @brief Join two edge geometries.
115  *
116  * For all edges in the model which refer to 'src_eg', change them to
117  * refer to 'dest_eg'. The source is destroyed.
118  *
119  * It is the responsibility of the caller to make certain that the
120  * 'dest_eg' is the best one for these edges. Outrageously wrong
121  * requests will cause this routine to abort.
122  *
123  * This algorithm does not make sense if dest_eg is an edge_g_cnurb;
124  * those only make sense in the parameter space of their associated
125  * face.
126  */
127 NMG_EXPORT extern void nmg_jeg(struct edge_g_lseg *dest_eg,
128  struct edge_g_lseg *src_eg);
129 
130 /**
131  * @brief Make wire edge.
132  *
133  * Make a new edge between a pair of vertices in a shell.
134  *
135  * A new vertex will be made for any NULL vertex pointer parameters.
136  * If we need to make a new vertex and the shell still has its
137  * vertexuse we reuse that vertex rather than freeing and
138  * re-allocating.
139  *
140  * If both vertices were specified, and the shell also had a vertexuse
141  * pointer, the vertexuse in the shell is killed. XXX Why?
142  *
143  * The explicit result is an edgeuse in shell "s" whose vertexuse refers to
144  * vertex v1. The edgeuse mate's vertexuse refers to vertex v2
145  *
146  * Additional possible side effects:
147  * -# If the shell had a lone vertex in vu_p, it is destroyed, even if both
148  * vertices were specified.
149  * -# The returned edgeuse is the first item on the shell's eu_hd list,
150  * followed immediately by the mate.
151  */
152 NMG_EXPORT extern struct edgeuse *nmg_me(struct vertex *v1,
153  struct vertex *v2,
154  struct shell *s);
155 #define nmg_mev(_v, _u) nmg_me((_v), (struct vertex *)NULL, (_u))
156 
157 /**
158  * @brief Make an edge on vertexuse.
159  *
160  * The new edge runs from and to that vertex.
161  *
162  * If the vertexuse was the shell's sole vertexuse, then the new edge
163  * is a wire edge in the shell's eu_hd list.
164  *
165  * If the vertexuse was part of a loop-of-a-single-vertex, either as a
166  * loop in a face or as a wire-loop in the shell, the loop becomes a
167  * regular loop with one edge that runs from and to the original
168  * vertex.
169  */
170 NMG_EXPORT extern struct edgeuse *nmg_meonvu(struct vertexuse *vu);
171 
172 /**
173  * @brief Delete an edgeuse & its mate from a shell or loop.
174  *
175  * @retval 0 If all is well
176  * @retval 1 If the parent now has no edgeuses, and is thus "illegal" and in
177  * need of being deleted. (The lu / shell deletion can't be handled at this
178  * level, and must be done by the caller).
179  */
180 NMG_EXPORT extern int nmg_keu(struct edgeuse *eu);
181 
182 /**
183  * Do two edgeuses share the same two vertices? If yes, eu's should be
184  * joined.
185  */
186 #define NMG_ARE_EUS_ADJACENT(_eu1, _eu2) (\
187  ((_eu1)->vu_p->v_p == (_eu2)->vu_p->v_p && \
188  (_eu1)->eumate_p->vu_p->v_p == (_eu2)->eumate_p->vu_p->v_p) || \
189  ((_eu1)->vu_p->v_p == (_eu2)->eumate_p->vu_p->v_p && \
190  (_eu1)->eumate_p->vu_p->v_p == (_eu2)->vu_p->v_p))
191 
192 /** Compat: Used in nmg_misc.c and nmg_mod.c */
193 #define EDGESADJ(_e1, _e2) NMG_ARE_EUS_ADJACENT(_e1, _e2)
194 
195 /**
196  * @brief If shell s2 has an edge that connects the same vertices as eu1 connects,
197  * return the matching edgeuse in s2.
198  *
199  * This routine works properly regardless of whether eu1 is in s2 or not.
200  * A convenient wrapper for nmg_findeu().
201  */
202 NMG_EXPORT extern struct edgeuse *nmg_find_matching_eu_in_s(const struct edgeuse *eu1,
203  const struct shell *s2);
204 
205 /**
206  * @brief Find an edgeuse in a shell between a given pair of vertex structs.
207  *
208  * If a given shell "s" is specified, then only edgeuses in that shell
209  * will be considered, otherwise all edgeuses in the model are fair game.
210  *
211  * If a particular edgeuse "eup" is specified, then that edgeuse
212  * and its mate will not be returned as a match.
213  *
214  * If "dangling_only" is true, then an edgeuse will be matched only if
215  * there are no other edgeuses on the edge, i.e. the radial edgeuse is
216  * the same as the mate edgeuse.
217  *
218  * @retval edgeuse* Edgeuse which matches the criteria
219  * @retval NULL Unable to find matching edgeuse
220  */
221 NMG_EXPORT extern struct edgeuse *nmg_findeu(const struct vertex *v1,
222  const struct vertex *v2,
223  const struct shell *s,
224  const struct edgeuse *eup,
225  int dangling_only);
226 
227 /**
228  * @brief An analog to nmg_findeu(), only restricted to searching a faceuse,
229  * rather than to a whole shell.
230  */
231 NMG_EXPORT extern struct edgeuse *nmg_find_eu_in_face(const struct vertex *v1,
232  const struct vertex *v2,
233  const struct faceuse *fu,
234  const struct edgeuse *eup,
235  int dangling_only);
236 
237 /**
238  * @brief Find an edge between a given pair of vertices.
239  *
240  * If a given shell "s" is specified, then only edges in that shell
241  * will be considered, otherwise all edges in the model are fair game.
242  *
243  * If a particular edge "ep" is specified, then that edge
244  * will not be returned as a match.
245  *
246  * @retval edgeuse* Edgeuse of an edge which matches the criteria
247  * @retval NULL Unable to find matching edge
248  */
249 NMG_EXPORT extern struct edgeuse *nmg_find_e(const struct vertex *v1,
250  const struct vertex *v2,
251  const struct shell *s,
252  const struct edge *ep);
253 
254 /**
255  * @brief Return a pointer to the edgeuse which is the parent of this vertexuse.
256  *
257  * A simple helper routine, which replaces the amazingly bad sequence of:
258  * nmg_find_eu_with_vu_in_lu(nmg_find_lu_of_vu(vu), vu)
259  * that was being used in several places.
260  */
261 NMG_EXPORT extern struct edgeuse *nmg_find_eu_of_vu(const struct vertexuse *vu);
262 
263 /**
264  * @brief Find an edgeuse starting at a given vertexuse within a loopuse.
265  */
266 NMG_EXPORT extern struct edgeuse *nmg_find_eu_with_vu_in_lu(const struct loopuse *lu,
267  const struct vertexuse *vu);
268 
269 /**
270  * @brief Looking radially around an edge, find another edge in the same
271  * face as the current edge. (this could be the mate to the current edge)
272  */
273 NMG_EXPORT extern const struct edgeuse *nmg_faceradial(const struct edgeuse *eu);
274 
275 /**
276  * @brief Looking radially around an edge, find another edge which is a part
277  * of a face in the same shell.
278  */
279 NMG_EXPORT extern const struct edgeuse *nmg_radial_face_edge_in_shell(const struct edgeuse *eu);
280 
281 /**
282  * @brief Perform a topology search to determine if two faces (specified by
283  * their faceuses) share an edge in common. If so, return an edgeuse
284  * in fu1 of that edge.
285  *
286  * If there are multiple edgeuses in common, ensure that they all refer
287  * to the same edge_g_lseg geometry structure. The intersection of two planes
288  * (non-coplanar) must be a single line.
289  *
290  * Calling this routine when the two faces share face geometry
291  * and have more than one edge in common gives
292  * a NULL return, as there is no unique answer.
293  *
294  * NULL is also returned if no common edge could be found.
295  */
296 NMG_EXPORT extern const struct edgeuse *nmg_find_edge_between_2fu(const struct faceuse *fu1,
297  const struct faceuse *fu2,
298  struct bu_list *vlfree,
299  const struct bn_tol *tol);
300 
301 /**
302  * @brief A geometric search routine to find the edge that is nearest to
303  * the given point, when all edges are projected into 2D using
304  * the matrix 'mat'.
305  * Useful for finding the edge nearest a mouse click, for example.
306  */
307 NMG_EXPORT extern struct edge *nmg_find_e_nearest_pt2(uint32_t *magic_p,
308  const point_t pt2,
309  const mat_t mat,
310  struct bu_list *vlfree,
311  const struct bn_tol *tol);
312 
313 /**
314  * @brief Given an edgeuse, return two arbitrary unit-length vectors which
315  * are perpendicular to each other and to the edgeuse, such that
316  * they can be considered the +X and +Y axis, and the edgeuse is +Z.
317  * That is, X cross Y = Z.
318  *
319  * Useful for erecting a coordinate system around an edge suitable
320  * for measuring the angles of other edges and faces with.
321  */
322 NMG_EXPORT extern void nmg_eu_2vecs_perp(vect_t xvec,
323  vect_t yvec,
324  vect_t zvec,
325  const struct edgeuse *eu,
326  const struct bn_tol *tol);
327 
328 /**
329  * @brief Given an edgeuse, if it is part of a faceuse, return the inward pointing
330  * "left" vector which points into the interior of this loop, and
331  * lies in the plane of the face. The left vector is unitized.
332  *
333  * This routine depends on the vertex ordering in an OT_SAME loopuse being
334  * properly CCW for exterior loops, and CW for interior (hole) loops.
335  *
336  * @retval -1 if edgeuse is not part of a faceuse.
337  * @retval 0 if left vector successfully computed into caller's array.
338  */
339 NMG_EXPORT extern int nmg_find_eu_leftvec(vect_t left,
340  const struct edgeuse *eu);
341 
342 /**
343  * @brief Given an edgeuse, if it is part of a faceuse, return the inward
344  * pointing "left" vector which points into the interior of this loop, and
345  * lies in the plane of the face. The left vector is not unitized.
346  *
347  * This routine depends on the vertex ordering in an OT_SAME loopuse being
348  * properly CCW for exterior loops, and CW for interior (hole) loops.
349  *
350  * @retval -1 if edgeuse is not part of a faceuse.
351  * @retval 0 if left vector successfully computed into caller's array.
352  */
353 NMG_EXPORT extern int nmg_find_eu_left_non_unit(vect_t left,
354  const struct edgeuse *eu);
355 
356 /**
357  * @brief If there is an edgeuse of an OT_SAME faceuse on this edge, return it.
358  * Only return a wire edgeuse if that is all there is.
359  *
360  * Useful for selecting a "good" edgeuse to pass to nmg_eu_2vecs_perp().
361  */
362 NMG_EXPORT extern struct edgeuse *nmg_find_ot_same_eu_of_e(const struct edge *e);
363 
364 /**
365  * @brief Check if a vertex is in use within a list of edges
366  *
367  * @retval 1 If found
368  * @retval 0 If not found
369  */
370 NMG_EXPORT extern int nmg_is_vertex_in_edgelist(const struct vertex *v,
371  const struct bu_list *hd);
372 
373 /**
374  * @brief Check if edge \b e is present within a list of edges
375  *
376  * @retval 1 If found
377  * @retval 0 If not found
378  */
379 NMG_EXPORT extern int nmg_is_edge_in_edgelist(const struct edge *e,
380  const struct bu_list *hd);
381 
382 /**
383  * @brief Build the set of pointers to all edgeuse structures in an NMG model
384  * that are "below" the data structure pointed to by magic_p, where magic_p is
385  * a pointer to the magic entry of any NMG data structure in the model.
386  *
387  * For "raw" geometric struts, the magic entry will be the first entry in the
388  * struct - for example, a loop pointed to by l would have a magic_p key of
389  * &l->magic. For the use structures, the magic key is found within the leading
390  * bu_list - for example, a faceuse pointed to by *fu would have a magic_p key
391  * at &fu->l.magic
392  *
393  * Each edgeuse pointer will be listed exactly once - i.e. uniqueness within
394  * the table may be assumed.
395  *
396  * @param[out] tab a bu_ptbl holding struct edgeuse pointers.
397  *
398  * @param magic_p pointer to an NMG data structure's magic entry.
399  *
400  * @param vlfree list of available vlist segments to be reused by debug drawing routines.
401  */
402 NMG_EXPORT extern void nmg_edgeuse_tabulate(struct bu_ptbl *tab,
403  const uint32_t *magic_p,
404  struct bu_list *vlfree);
405 
406 /**
407  * @brief Build the set of pointers to all edge structures in an NMG model
408  * that are "below" the data structure pointed to by magic_p, where magic_p is
409  * a pointer to the magic entry of any NMG data structure in the model.
410  *
411  * For "raw" geometric struts, the magic entry will be the first entry in the
412  * struct - for example, a loop pointed to by l would have a magic_p key of
413  * &l->magic. For the use structures, the magic key is found within the leading
414  * bu_list - for example, a faceuse pointed to by *fu would have a magic_p key
415  * at &fu->l.magic
416  *
417  * Each edge pointer will be listed exactly once - i.e. uniqueness within
418  * the table may be assumed.
419  *
420  * @param[out] tab a bu_ptbl holding struct edge pointers.
421  *
422  * @param magic_p pointer to an NMG data structure's magic entry.
423  *
424  * @param vlfree list of available vlist segments to be reused by debug drawing routines.
425  */
426 NMG_EXPORT extern void nmg_edge_tabulate(struct bu_ptbl *tab,
427  const uint32_t *magic_p,
428  struct bu_list *vlfree);
429 
430 /**
431  * @brief Build the set of pointers to all edge geometry structures in an NMG
432  * model that are "below" the data structure pointed to by magic_p, where
433  * magic_p is a pointer to the magic entry of any NMG data structure in the
434  * model.
435  *
436  * For "raw" geometric struts, the magic entry will be the first entry in the
437  * struct - for example, a loop pointed to by l would have a magic_p key of
438  * &l->magic. For the use structures, the magic key is found within the leading
439  * bu_list - for example, a faceuse pointed to by *fu would have a magic_p key
440  * at &fu->l.magic
441  *
442  * @param[out] tab a bu_ptbl holding edge geometry pointers.
443  *
444  * @param magic_p pointer to an NMG data structure's magic entry.
445  *
446  * @param vlfree list of available vlist segments to be reused by debug drawing routines.
447  *
448  * Each edge geometry pointer will be listed exactly once - i.e. uniqueness
449  * within the table may be assumed. However, the type of edge geometry stored
450  * is *not* necessarily unique - both edge_g_lseg and edge_g_cnurb structures will
451  * be stashed by this routine. It is the responsibility of the caller to check
452  * their magic numbers to sort out the type of each pointer:
453  *
454  * @code
455  * struct bu_ptbl edge_g_tbl;
456  * bu_ptbl_init(&edge_g_tbl, 64, "&edge_g_tbl");
457  * nmg_edge_g_tabulate(&edge_g_tbl, &fu->l.magic, vlfree);
458  * for (int i=0; i < BU_PTBL_LEN(&edge_g_tbl); i++) {
459  * struct edge_g_lseg *elg;
460  * struct edge_g_cnurb *ecg;
461  * long *ep = BU_PTBL_GET(&edge_g_tbl, i);
462  * switch (*ep) {
463  * case NMG_EDGE_G_LSEG_MAGIC:
464  * elg = (struct edge_g_lseg *)ep;
465  * NMG_CK_EDGE_G_LSEG(elg);
466  * break;
467  * case NMG_EDGE_G_CNURB_MAGIC:
468  * ecg = (struct edge_g_cnurb *)ep;
469  * NMG_CK_EDGE_G_CNURB(ecg);
470  * break;
471  * default
472  * bu_log("Error - invalid edge geometry type\n");
473  * }
474  * }
475  * @endcode
476  */
477 NMG_EXPORT extern void nmg_edge_g_tabulate(struct bu_ptbl *tab,
478  const uint32_t *magic_p,
479  struct bu_list *vlfree);
480 /**
481  * @brief Build an bu_ptbl list which cites every edgeuse pointer that uses
482  * edge geometry "eg".
483  *
484  * The edge geometry has this information encoded within it, so this is largely
485  * a convenience routine to allow the caller to avoid bu_list based iteration
486  * which must understand the edge geometry containers and instead use the
487  * simpler bu_ptbl iteration.
488  */
489 NMG_EXPORT extern void nmg_edgeuse_with_eg_tabulate(struct bu_ptbl *tab,
490  const struct edge_g_lseg *eg);
491 /**
492  * @brief Given a pointer to any nmg data structure,
493  * build an bu_ptbl list which cites every edgeuse
494  * pointer from there on "down" in the model
495  * that has both vertices within tolerance of the given line.
496  *
497  * XXX This routine is a potential source of major trouble.
498  * XXX If there are "nearby" edges that "should" be on the list but
499  * XXX don't make it, then the intersection calculations might
500  * XXX miss important intersections.
501  * As an admittedly grubby workaround, use 10X the distance tol here,
502  * just to get more candidates onto the list.
503  * The caller will have to wrestle with the added fuzz.
504  */
505 NMG_EXPORT extern void nmg_edgeuse_on_line_tabulate(struct bu_ptbl *tab,
506  const uint32_t *magic_p,
507  const point_t pt,
508  const vect_t dir,
509  struct bu_list *vlfree,
510  const struct bn_tol *tol);
511 
512 /**
513  * @brief Build lists of all edges (represented by one edgeuse on that edge)
514  * and all vertices found underneath the NMG entity indicated by magic_p.
515  */
516 NMG_EXPORT extern void nmg_e_and_v_tabulate(struct bu_ptbl *eutab,
517  struct bu_ptbl *vtab,
518  const uint32_t *magic_p,
519  struct bu_list *vlfree);
520 
521 /**
522  * Given two edgeuses, determine if they share the same edge geometry,
523  * either topologically, or within tolerance.
524  *
525  * @retval 0 two edge geometries are not coincident
526  * @retval 1 edges geometries are everywhere coincident.
527  * (For linear edge_g_lseg, the 2 are the same line, within tol.)
528  */
529 NMG_EXPORT extern int nmg_2edgeuse_g_coincident(const struct edgeuse *eu1,
530  const struct edgeuse *eu2,
531  const struct bn_tol *tol);
532 
533 /**
534  * @brief Sets the "is_real" flag on all edges at or below the pointer
535  * passed. Returns the number of flags set.
536  */
537 NMG_EXPORT extern int nmg_mark_edges_real(const uint32_t *magic_p, struct bu_list *vlfree);
538 
539 /**
540  * @brief Convenience wrapper to retrieve and remove the last edgeuse element
541  * from the \b stack bu_ptbl.
542  */
543 NMG_EXPORT extern struct edgeuse *nmg_pop_eu(struct bu_ptbl *stack);
544 
545 /**
546  * @brief Moves indicated edgeuse (mv_eu) so that it passes thru the given
547  * point (pt). The direction of the edgeuse is not changed, so new edgeuse is
548  * parallel to the original.
549  *
550  * Plane equations of all radial faces on this edge are changed and all
551  * vertices (except one anchor point) in radial loops are adjusted Note that
552  * the anchor point is chosen arbitrarily.
553  *
554  * @retval 1 failure
555  * @retval 0 success
556  */
557 NMG_EXPORT extern int nmg_move_edge_thru_pnt(struct edgeuse *mv_eu,
558  const point_t pt,
559  const struct bn_tol *tol);
560 
561 /**
562  * @brief Split an edge into multiple edges at specified vertices if they
563  * are within tolerance distance.
564  *
565  * Returns the number of additional edges that were created.
566  */
567 NMG_EXPORT extern int nmg_break_edge_at_verts(struct edge *e,
568  struct bu_ptbl *verts,
569  const struct bn_tol *tol);
570 
571 /**
572  * @brief Apply nmg_break_edge_at_verts() to all edge/vertex combinations present
573  * in the NMG model below the NMG element with the magic number pointed to by
574  * \b magic_p
575  */
576 NMG_EXPORT extern int nmg_break_edges(uint32_t *magic_p, struct bu_list *vlfree,
577  const struct bn_tol *tol);
578 
579 /**
580  * @brief Fuse vertices and edges according to \b tol
581  *
582  * TODO - this needs MUCH better documentation...
583  *
584  * If a bu_ptbl structure is passed into this function, the structure must
585  * contain edgeuse. Vertices will then be fused at the shell level. If an NMG
586  * structure is passed into this function, if the structure is an NMG region or
587  * model, vertices will be fused at the model level. If the NMG structure
588  * passed in is a shell or anything lower, vertices will be fused at the shell
589  * level.
590  */
591 NMG_EXPORT extern int nmg_edge_fuse(const uint32_t *magic_p,struct bu_list *vlfree,
592  const struct bn_tol *tol);
593 
594 /**
595  * @brief Fuse edge_g structs.
596  *
597  * TODO - this needs MUCH better documentation...
598  */
599 NMG_EXPORT extern int nmg_edge_g_fuse(const uint32_t *magic_p,struct bu_list *vlfree,
600  const struct bn_tol *tol);
601 
602 /**
603  * @brief Given two edgeuses with different edge geometry but running between
604  * the same two vertices, select the proper edge geometry to associate with.
605  *
606  * Really, there are 3 geometries to be compared here: the vector between the
607  * two endpoints of this edge, and the two edge_g structures. Rather than
608  * always taking eu2 or eu1, select the one that best fits this one edge.
609  *
610  * Consider fu1:
611  * @verbatim
612  B
613  *
614  /|
615  eg2/ |
616  / |
617  D/ |
618  * |
619  / |
620  A *-*----* C
621  E eg1
622  @endverbatim
623  *
624  * At the start of a face/face intersection, eg1 runs from A to C,
625  * and eg2 runs ADB. The line of intersection with the other face
626  * (fu2, not drawn) lies along eg1.
627  * Assume that edge AC needs to be broken at E,
628  * where E is just a little more than tol->dist away from A.
629  * Existing point D is found because it *is* within tol->dist of E,
630  * thanks to the cosine of angle BAC.
631  * So, edge AC is broken on vertex D, and the intersection list
632  * contains vertexuses A, E, and C.
633  *
634  * Because D and E are the same point, fu1 has become a triangle with
635  * a little "spike" on the end. If this is handled simply by re-homing
636  * edge AE to eg2, it may cause trouble, because eg1 now runs EC,
637  * but the geometry for eg1 runs AC. If there are other vertices on
638  * edge eg1, the problem can not be resolved simply by recomputing the
639  * geometry of eg1.
640  * Since E (D) is within tolerance of eg1, it is not unreasonable
641  * just to leave eg1 alone.
642  *
643  * The issue boils down to selecting whether the existing eg1 or eg2
644  * best represents the direction of the little stub edge AD (shared with AE).
645  * In this case, eg2 is the correct choice, as AD (and AE) lie on line AB.
646  *
647  * It would be disastrous to force *all* of eg1 to use the edge geometry
648  * of eg2, as the two lines are very different.
649  */
650 NMG_EXPORT extern struct edge_g_lseg *nmg_pick_best_edge_g(struct edgeuse *eu1,
651  struct edgeuse *eu2,
652  const struct bn_tol *tol);
653 
654 /**
655  * @brief Check if \b eu is part of a loop but is not correctly connected
656  * topologically to other edges in the loop.
657  */
658 NMG_EXPORT extern int nmg_eu_is_part_of_crack(const struct edgeuse *eu);
659 
660 /**
661  * @brief Make all the edgeuses around eu2's edge to refer to eu1's edge,
662  * taking care to organize them into the proper angular orientation, so that
663  * the attached faces are correctly arranged radially around the edge.
664  *
665  * This depends on both edges being part of face loops, with vertex and face
666  * geometry already associated.
667  *
668  * The two edgeuses being joined might well be from separate shells, so the
669  * issue of preserving (simple) faceuse orientation parity (SAME, OPPOSITE,
670  * OPPOSITE, SAME, ...) can't be used here -- that only applies to faceuses
671  * from the same shell.
672  *
673  * Some of the edgeuses around both edges may be wires.
674  *
675  * Call to nmg_check_radial at end has been deleted. Note that after two
676  * radial EU's have been joined a third cannot be joined to them without
677  * creating unclosed space that nmg_check_radial will find.
678  */
679 NMG_EXPORT extern void nmg_radial_join_eu(struct edgeuse *eu1,
680  struct edgeuse *eu2,
681  const struct bn_tol *tol);
682 
683 /**
684  * @brief TODO - document...
685  */
686 NMG_EXPORT extern int nmg_break_all_es_on_v(uint32_t *magic_p,
687  struct vertex *v,struct bu_list *vlfree,
688  const struct bn_tol *tol);
689 
690 /**
691  * @brief As the first step in evaluating a boolean formula,
692  * before starting to do face/face intersections, compare every
693  * edge in the model with every vertex in the model.
694  *
695  * If the vertex is within tolerance of the edge, break the edge,
696  * and enroll the new edge on a list of edges still to be processed.
697  *
698  * A list of edges and a list of vertices are built, and then processed.
699  *
700  * Space partitioning could improve the performance of this algorithm.
701  * For the moment, a brute-force approach is used.
702  *
703  * @return
704  * Number of edges broken.
705  */
706 NMG_EXPORT extern int nmg_break_e_on_v(const uint32_t *magic_p,struct bu_list *vlfree,
707  const struct bn_tol *tol);
708 
709 /**
710  * @brief Determine if the given wedge is entirely to the left or right of the
711  * ray, or if it crosses.
712  *
713  * 0 degrees is to the rear (ON_REV), 90 degrees is to the RIGHT, 180 is
714  * ON_FORW, 270 is to the LEFT.
715  *
716  * "halfway X" (ha, hb) have these properties:
717  * @verbatim
718  < 0 (==> X < 180) RIGHT
719  > 0 (==> X > 180) LEFT
720  ==0 (==> X == 180) ON_FORW
721  @endverbatim
722  *
723  * Possible return values are WEDGE_LEFT, WEDGE_CROSSING, WEDGE_RIGHT, and
724  * WEDGE_ON
725  */
726 NMG_EXPORT extern int nmg_wedge_class(int ass, /* assessment of two edges forming wedge */
727  double a,
728  double b);
729 
730 __END_DECLS
731 
732 #endif /* NMG_EDGE_H */
733 /** @} */
734 /*
735  * Local Variables:
736  * mode: C
737  * tab-width: 8
738  * indent-tabs-mode: t
739  * c-file-style: "stroustrup"
740  * End:
741  * ex: shiftwidth=4 tabstop=8
742  */
Header file for the BRL-CAD common definitions.
void nmg_edgeuse_on_line_tabulate(struct bu_ptbl *tab, const uint32_t *magic_p, const point_t pt, const vect_t dir, struct bu_list *vlfree, const struct bn_tol *tol)
Given a pointer to any nmg data structure, build an bu_ptbl list which cites every edgeuse pointer fr...
void nmg_edge_g_tabulate(struct bu_ptbl *tab, const uint32_t *magic_p, struct bu_list *vlfree)
Build the set of pointers to all edge geometry structures in an NMG model that are "below" the data s...
struct edgeuse * nmg_find_matching_eu_in_s(const struct edgeuse *eu1, const struct shell *s2)
If shell s2 has an edge that connects the same vertices as eu1 connects, return the matching edgeuse ...
int nmg_find_eu_leftvec(vect_t left, const struct edgeuse *eu)
Given an edgeuse, if it is part of a faceuse, return the inward pointing "left" vector which points i...
void nmg_edge_g(struct edgeuse *eu)
Compute the equation of the line formed by the endpoints of the edge.
int nmg_edge_fuse(const uint32_t *magic_p, struct bu_list *vlfree, const struct bn_tol *tol)
Fuse vertices and edges according to tol.
struct edgeuse * nmg_meonvu(struct vertexuse *vu)
Make an edge on vertexuse.
struct edgeuse * nmg_pop_eu(struct bu_ptbl *stack)
Convenience wrapper to retrieve and remove the last edgeuse element from the stack bu_ptbl.
struct edgeuse * nmg_find_eu_of_vu(const struct vertexuse *vu)
Return a pointer to the edgeuse which is the parent of this vertexuse.
int nmg_move_edge_thru_pnt(struct edgeuse *mv_eu, const point_t pt, const struct bn_tol *tol)
Moves indicated edgeuse (mv_eu) so that it passes thru the given point (pt). The direction of the edg...
struct edge_g_lseg * nmg_pick_best_edge_g(struct edgeuse *eu1, struct edgeuse *eu2, const struct bn_tol *tol)
Given two edgeuses with different edge geometry but running between the same two vertices,...
int nmg_find_eu_left_non_unit(vect_t left, const struct edgeuse *eu)
Given an edgeuse, if it is part of a faceuse, return the inward pointing "left" vector which points i...
void nmg_edgeuse_with_eg_tabulate(struct bu_ptbl *tab, const struct edge_g_lseg *eg)
Build an bu_ptbl list which cites every edgeuse pointer that uses edge geometry "eg".
int nmg_keu(struct edgeuse *eu)
Delete an edgeuse & its mate from a shell or loop.
struct edgeuse * nmg_find_eu_with_vu_in_lu(const struct loopuse *lu, const struct vertexuse *vu)
Find an edgeuse starting at a given vertexuse within a loopuse.
struct edgeuse * nmg_me(struct vertex *v1, struct vertex *v2, struct shell *s)
Make wire edge.
struct edge * nmg_find_e_nearest_pt2(uint32_t *magic_p, const point_t pt2, const mat_t mat, struct bu_list *vlfree, const struct bn_tol *tol)
A geometric search routine to find the edge that is nearest to the given point, when all edges are pr...
int nmg_edge_g_fuse(const uint32_t *magic_p, struct bu_list *vlfree, const struct bn_tol *tol)
Fuse edge_g structs.
void nmg_unglueedge(struct edgeuse *eu)
If edgeuse is part of a shared edge (more than one pair of edgeuses on the edge), it and its mate are...
const struct edgeuse * nmg_find_edge_between_2fu(const struct faceuse *fu1, const struct faceuse *fu2, struct bu_list *vlfree, const struct bn_tol *tol)
Perform a topology search to determine if two faces (specified by their faceuses) share an edge in co...
void nmg_eu_2vecs_perp(vect_t xvec, vect_t yvec, vect_t zvec, const struct edgeuse *eu, const struct bn_tol *tol)
Given an edgeuse, return two arbitrary unit-length vectors which are perpendicular to each other and ...
int nmg_break_edges(uint32_t *magic_p, struct bu_list *vlfree, const struct bn_tol *tol)
Apply nmg_break_edge_at_verts() to all edge/vertex combinations present in the NMG model below the NM...
int nmg_break_edge_at_verts(struct edge *e, struct bu_ptbl *verts, const struct bn_tol *tol)
Split an edge into multiple edges at specified vertices if they are within tolerance distance.
void nmg_je(struct edgeuse *eudst, struct edgeuse *eusrc)
Move a pair of edgeuses onto a single edge (glue edgeuse).
int nmg_wedge_class(int ass, double a, double b)
Determine if the given wedge is entirely to the left or right of the ray, or if it crosses.
int nmg_break_all_es_on_v(uint32_t *magic_p, struct vertex *v, struct bu_list *vlfree, const struct bn_tol *tol)
struct edgeuse * nmg_find_e(const struct vertex *v1, const struct vertex *v2, const struct shell *s, const struct edge *ep)
Find an edge between a given pair of vertices.
int nmg_mark_edges_real(const uint32_t *magic_p, struct bu_list *vlfree)
Sets the "is_real" flag on all edges at or below the pointer passed. Returns the number of flags set.
const struct edgeuse * nmg_faceradial(const struct edgeuse *eu)
Looking radially around an edge, find another edge in the same face as the current edge....
const struct edgeuse * nmg_radial_face_edge_in_shell(const struct edgeuse *eu)
Looking radially around an edge, find another edge which is a part of a face in the same shell.
int nmg_use_edge_g(struct edgeuse *eu, uint32_t *magic_p)
Associate edgeuse 'eu' with the edge geometry structure identified by 'magic_p', where magic_p is the...
int nmg_demote_eu(struct edgeuse *eu)
Demote a wire edge into a pair of self-loop vertices.
int nmg_is_edge_in_edgelist(const struct edge *e, const struct bu_list *hd)
Check if edge e is present within a list of edges.
int nmg_is_vertex_in_edgelist(const struct vertex *v, const struct bu_list *hd)
Check if a vertex is in use within a list of edges.
int nmg_break_e_on_v(const uint32_t *magic_p, struct bu_list *vlfree, const struct bn_tol *tol)
As the first step in evaluating a boolean formula, before starting to do face/face intersections,...
void nmg_edgeuse_tabulate(struct bu_ptbl *tab, const uint32_t *magic_p, struct bu_list *vlfree)
Build the set of pointers to all edgeuse structures in an NMG model that are "below" the data structu...
struct edgeuse * nmg_findeu(const struct vertex *v1, const struct vertex *v2, const struct shell *s, const struct edgeuse *eup, int dangling_only)
Find an edgeuse in a shell between a given pair of vertex structs.
struct edgeuse * nmg_find_ot_same_eu_of_e(const struct edge *e)
If there is an edgeuse of an OT_SAME faceuse on this edge, return it. Only return a wire edgeuse if t...
void nmg_jeg(struct edge_g_lseg *dest_eg, struct edge_g_lseg *src_eg)
Join two edge geometries.
void nmg_e_and_v_tabulate(struct bu_ptbl *eutab, struct bu_ptbl *vtab, const uint32_t *magic_p, struct bu_list *vlfree)
Build lists of all edges (represented by one edgeuse on that edge) and all vertices found underneath ...
void nmg_radial_join_eu(struct edgeuse *eu1, struct edgeuse *eu2, const struct bn_tol *tol)
Make all the edgeuses around eu2's edge to refer to eu1's edge, taking care to organize them into the...
struct edgeuse * nmg_find_eu_in_face(const struct vertex *v1, const struct vertex *v2, const struct faceuse *fu, const struct edgeuse *eup, int dangling_only)
An analog to nmg_findeu(), only restricted to searching a faceuse, rather than to a whole shell.
int nmg_2edgeuse_g_coincident(const struct edgeuse *eu1, const struct edgeuse *eu2, const struct bn_tol *tol)
void nmg_edge_tabulate(struct bu_ptbl *tab, const uint32_t *magic_p, struct bu_list *vlfree)
Build the set of pointers to all edge structures in an NMG model that are "below" the data structure ...
int nmg_eu_is_part_of_crack(const struct edgeuse *eu)
Check if eu is part of a loop but is not correctly connected topologically to other edges in the loop...
fastf_t vect_t[ELEMENTS_PER_VECT]
3-tuple vector
Definition: vmath.h:349
fastf_t mat_t[ELEMENTS_PER_MAT]
4x4 matrix
Definition: vmath.h:370
fastf_t point_t[ELEMENTS_PER_POINT]
3-tuple point
Definition: vmath.h:355
Definition: tol.h:72
Definition: list.h:132
Definition: ptbl.h:53
Line in 3D space.
Definition: topology.h:326
NMG topological edge.
Definition: topology.h:144
NMG topological edge usage.
Definition: topology.h:155
uint32_t * magic_p
for those times when we're not sure
Definition: topology.h:161
NMG topological face usage.
Definition: topology.h:230
NMG topological loop usage.
Definition: topology.h:192
NMG topological shell.
Definition: topology.h:261
NMG topological vertex - the simplest element of the topology system.
Definition: topology.h:98
NMG topological vertex usage.
Definition: topology.h:109
fundamental vector, matrix, quaternion math macros