BRL-CAD
nmg_index.c
Go to the documentation of this file.
1 /* N M G _ I N D E X . C
2  * BRL-CAD
3  *
4  * Copyright (c) 1990-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_index.c
23  *
24  * Handle counting and re-indexing of NMG data structures.
25  *
26  */
27 /** @} */
28 
29 #include "common.h"
30 
31 #include <stddef.h>
32 #include <string.h>
33 #include <math.h>
34 #include "bio.h"
35 
36 #include "vmath.h"
37 #include "nmg.h"
38 #include "raytrace.h"
39 
40 /**
41  * Return the structure index number of an arbitrary NMG structure.
42  *
43  * Returns -
44  * >=0 index number
45  * -1 pointed at struct bu_list embedded within NMG structure.
46  * -2 error: unknown magic number
47  */
48 int
49 nmg_index_of_struct(register const uint32_t *p)
50 {
51  switch (*p) {
52  case NMG_MODEL_MAGIC:
53  return ((struct model *)p)->index;
54  case NMG_REGION_MAGIC:
55  return ((struct nmgregion *)p)->index;
56  case NMG_REGION_A_MAGIC:
57  return ((struct nmgregion_a *)p)->index;
58  case NMG_SHELL_MAGIC:
59  return ((struct shell *)p)->index;
60  case NMG_SHELL_A_MAGIC:
61  return ((struct shell_a *)p)->index;
62  case NMG_FACEUSE_MAGIC:
63  return ((struct faceuse *)p)->index;
64  case NMG_FACE_MAGIC:
65  return ((struct face *)p)->index;
67  return ((struct face_g_plane *)p)->index;
69  return ((struct face_g_snurb *)p)->index;
70  case NMG_LOOPUSE_MAGIC:
71  return ((struct loopuse *)p)->index;
72  case NMG_LOOP_MAGIC:
73  return ((struct loop *)p)->index;
74  case NMG_LOOP_G_MAGIC:
75  return ((struct loop_g *)p)->index;
76  case NMG_EDGEUSE_MAGIC:
77  return ((struct edgeuse *)p)->index;
78  case NMG_EDGEUSE2_MAGIC:
79  /* Points to l2 inside edgeuse */
80  return BU_LIST_MAIN_PTR(edgeuse, p, l2)->index;
81  case NMG_EDGE_MAGIC:
82  return ((struct edge *)p)->index;
84  return ((struct edge_g_lseg *)p)->index;
86  return ((struct edge_g_cnurb *)p)->index;
88  return ((struct vertexuse *)p)->index;
90  return ((struct vertexuse_a_plane *)p)->index;
92  return ((struct vertexuse_a_cnurb *)p)->index;
93  case NMG_VERTEX_MAGIC:
94  return ((struct vertex *)p)->index;
95  case NMG_VERTEX_G_MAGIC:
96  return ((struct vertex_g *)p)->index;
97  case BU_LIST_HEAD_MAGIC:
98  /* indicate special list head encountered */
99  return -1;
100  }
101  /* default */
102  bu_log("nmg_index_of_struct: magicp = %p, magic = %x\n", (void *)p, *p);
103  return -2; /* indicate error */
104 }
105 
106 
107 #define NMG_HIGH_BIT 0x80000000
108 
109 #define NMG_MARK_INDEX(_p) ((_p)->index |= NMG_HIGH_BIT)
110 
111 #define NMG_ASSIGN_NEW_INDEX(_p) \
112  { if (((_p)->index & NMG_HIGH_BIT) != 0) \
113  (_p)->index = newindex++; }
114 
115 /**
116  * Helper routine
117  */
118 static void
119 nmg_mark_edge_g(uint32_t *magic_p)
120 {
121  if (!magic_p) bu_bomb("nmg_mark_edge_g bad magic\n");
122  switch (*magic_p) {
123  case NMG_EDGE_G_LSEG_MAGIC: {
124  struct edge_g_lseg *lseg = (struct edge_g_lseg *)magic_p;
125  NMG_MARK_INDEX(lseg);
126  return;
127  }
128  case NMG_EDGE_G_CNURB_MAGIC: {
129  struct edge_g_cnurb *cnurb = (struct edge_g_cnurb *)magic_p;
130  NMG_MARK_INDEX(cnurb);
131  return;
132  }
133  }
134  bu_bomb("nmg_mark_edge_g() unknown magic\n");
135 }
136 
137 
138 /**
139  * First pass: just set the high bit on all index words
140  *
141  * This is a separate function largely for the benefit of global optimizers,
142  * which tended to blow their brains out on such a large subroutine.
143  */
144 void
145 nmg_m_set_high_bit(struct model *m)
146 {
147  struct nmgregion *r;
148  struct shell *s;
149  struct faceuse *fu;
150  struct face *f;
151  struct loopuse *lu;
152  struct loop *l;
153  register struct edgeuse *eu;
154  struct edge *e;
155  register struct vertexuse *vu;
156 
157 #define MARK_VU(_vu) { \
158  struct vertex *v; \
159  NMG_CK_VERTEXUSE(_vu); \
160  NMG_MARK_INDEX(_vu); \
161  if (_vu->a.magic_p) switch (*_vu->a.magic_p) { \
162  case NMG_VERTEXUSE_A_PLANE_MAGIC: \
163  NMG_MARK_INDEX(_vu->a.plane_p); \
164  break; \
165  case NMG_VERTEXUSE_A_CNURB_MAGIC: \
166  NMG_MARK_INDEX(_vu->a.cnurb_p); \
167  break; \
168  } \
169  v = _vu->v_p; \
170  NMG_CK_VERTEX(v); \
171  NMG_MARK_INDEX(v); \
172  if (v->vg_p) { \
173  NMG_CK_VERTEX_G(v->vg_p); \
174  NMG_MARK_INDEX(v->vg_p); \
175  } \
176  }
177 
178  NMG_CK_MODEL(m);
179  NMG_MARK_INDEX(m);
180 
181  for (BU_LIST_FOR(r, nmgregion, &m->r_hd)) {
182  NMG_CK_REGION(r);
183  NMG_MARK_INDEX(r);
184  if (r->ra_p) {
185  NMG_CK_REGION_A(r->ra_p);
186  NMG_MARK_INDEX(r->ra_p);
187  }
188  for (BU_LIST_FOR(s, shell, &r->s_hd)) {
189  NMG_CK_SHELL(s);
190  NMG_MARK_INDEX(s);
191  if (s->sa_p) {
192  NMG_CK_SHELL_A(s->sa_p);
193  NMG_MARK_INDEX(s->sa_p);
194  }
195  /* Faces in shell */
196  for (BU_LIST_FOR(fu, faceuse, &s->fu_hd)) {
197  NMG_CK_FACEUSE(fu);
198  NMG_MARK_INDEX(fu);
199  f = fu->f_p;
200  NMG_CK_FACE(f);
201  NMG_MARK_INDEX(f);
202  if (f->g.magic_p) switch (*f->g.magic_p) {
204  NMG_MARK_INDEX(f->g.plane_p);
205  break;
207  NMG_MARK_INDEX(f->g.snurb_p);
208  break;
209  }
210  /* Loops in face */
211  for (BU_LIST_FOR(lu, loopuse, &fu->lu_hd)) {
212  NMG_CK_LOOPUSE(lu);
213  NMG_MARK_INDEX(lu);
214  l = lu->l_p;
215  NMG_CK_LOOP(l);
216  NMG_MARK_INDEX(l);
217  if (l->lg_p) {
218  NMG_CK_LOOP_G(l->lg_p);
219  NMG_MARK_INDEX(l->lg_p);
220  }
221  if (BU_LIST_FIRST_MAGIC(&lu->down_hd) == NMG_VERTEXUSE_MAGIC) {
222  /* Loop of Lone vertex */
223  vu = BU_LIST_FIRST(vertexuse, &lu->down_hd);
224  MARK_VU(vu);
225  continue;
226  }
227  for (BU_LIST_FOR(eu, edgeuse, &lu->down_hd)) {
228  NMG_CK_EDGEUSE(eu);
229  NMG_MARK_INDEX(eu);
230  e = eu->e_p;
231  NMG_CK_EDGE(e);
232  NMG_MARK_INDEX(e);
233  if (eu->g.magic_p) nmg_mark_edge_g(eu->g.magic_p);
234  vu = eu->vu_p;
235  MARK_VU(vu);
236  }
237  }
238  }
239  /* Wire loops in shell */
240  for (BU_LIST_FOR(lu, loopuse, &s->lu_hd)) {
241  NMG_CK_LOOPUSE(lu);
242  NMG_MARK_INDEX(lu);
243  l = lu->l_p;
244  NMG_CK_LOOP(l);
245  NMG_MARK_INDEX(l);
246  if (l->lg_p) {
247  NMG_CK_LOOP_G(l->lg_p);
248  NMG_MARK_INDEX(l->lg_p);
249  }
250  if (BU_LIST_FIRST_MAGIC(&lu->down_hd) == NMG_VERTEXUSE_MAGIC) {
251  /* Wire loop of Lone vertex */
252  vu = BU_LIST_FIRST(vertexuse, &lu->down_hd);
253  MARK_VU(vu);
254  continue;
255  }
256  for (BU_LIST_FOR(eu, edgeuse, &lu->down_hd)) {
257  NMG_CK_EDGEUSE(eu);
258  NMG_MARK_INDEX(eu);
259  e = eu->e_p;
260  NMG_CK_EDGE(e);
261  NMG_MARK_INDEX(e);
262  if (eu->g.magic_p) nmg_mark_edge_g(eu->g.magic_p);
263  vu = eu->vu_p;
264  MARK_VU(vu);
265  }
266  }
267  /* Wire edges in shell */
268  for (BU_LIST_FOR(eu, edgeuse, &s->eu_hd)) {
269  NMG_CK_EDGEUSE(eu);
270  NMG_MARK_INDEX(eu);
271  e = eu->e_p;
272  NMG_CK_EDGE(e);
273  NMG_MARK_INDEX(e);
274  if (eu->g.magic_p) nmg_mark_edge_g(eu->g.magic_p);
275  vu = eu->vu_p;
276  MARK_VU(vu);
277  }
278  /* Lone vertex in shell */
279  vu = s->vu_p;
280  if (vu) {
281  MARK_VU(vu);
282  }
283  }
284  }
285 #undef MARK_VU
286 }
287 
288 
289 /**
290  * Reassign index numbers to all the data structures in a model.
291  * The model structure will get index 0, all others will be sequentially
292  * assigned after that.
293  *
294  * Because the first pass has done extensive error checking,
295  * the second pass can do less.
296  */
297 void
298 nmg_m_reindex(struct model *m, register long int newindex)
299 {
300  struct nmgregion *r;
301  struct shell *s;
302  struct faceuse *fu;
303  struct face *f;
304  struct loopuse *lu;
305  struct loop *l;
306  register struct edgeuse *eu;
307  struct edge *e;
308  register struct vertexuse *vu;
309  struct vertex *v;
310 
311 #define ASSIGN_VU(_vu) { \
312  NMG_CK_VERTEXUSE(_vu); \
313  NMG_ASSIGN_NEW_INDEX(_vu); \
314  if (_vu->a.magic_p) switch (*_vu->a.magic_p) { \
315  case NMG_VERTEXUSE_A_PLANE_MAGIC: \
316  NMG_ASSIGN_NEW_INDEX(_vu->a.plane_p); \
317  break; \
318  case NMG_VERTEXUSE_A_CNURB_MAGIC: \
319  NMG_ASSIGN_NEW_INDEX(_vu->a.cnurb_p); \
320  break; \
321  } \
322  v = _vu->v_p; \
323  NMG_CK_VERTEX(v); \
324  NMG_ASSIGN_NEW_INDEX(v); \
325  if (v->vg_p) NMG_ASSIGN_NEW_INDEX(v->vg_p); \
326  }
327 
328  NMG_CK_MODEL(m);
329  if (m->index != 0) bu_log("nmg_m_reindex() m->index=%ld\n", m->index);
330  if (newindex < 0) bu_log("nmg_m_reindex() newindex(%ld) < 0\n", newindex);
331 
332  /* First pass: set high bits */
334 
335  /*
336  * Second pass: assign new index number
337  */
338 
340  for (BU_LIST_FOR(r, nmgregion, &m->r_hd)) {
341  NMG_CK_REGION(r);
343  if (r->ra_p) NMG_ASSIGN_NEW_INDEX(r->ra_p);
344  for (BU_LIST_FOR(s, shell, &r->s_hd)) {
345  NMG_CK_SHELL(s);
347  if (s->sa_p) NMG_ASSIGN_NEW_INDEX(s->sa_p);
348  /* Faces in shell */
349  for (BU_LIST_FOR(fu, faceuse, &s->fu_hd)) {
350  NMG_CK_FACEUSE(fu);
352  f = fu->f_p;
353  NMG_CK_FACE(f);
355  if (f->g.plane_p) switch (*f->g.magic_p) {
357  NMG_ASSIGN_NEW_INDEX(f->g.plane_p);
358  break;
360  NMG_ASSIGN_NEW_INDEX(f->g.snurb_p);
361  break;
362  }
363  /* Loops in face */
364  for (BU_LIST_FOR(lu, loopuse, &fu->lu_hd)) {
365  NMG_CK_LOOPUSE(lu);
367  l = lu->l_p;
368  NMG_CK_LOOP(l);
370  if (l->lg_p) NMG_ASSIGN_NEW_INDEX(l->lg_p);
371  if (BU_LIST_FIRST_MAGIC(&lu->down_hd) == NMG_VERTEXUSE_MAGIC) {
372  /* Loop of Lone vertex */
373  vu = BU_LIST_FIRST(vertexuse, &lu->down_hd);
374  ASSIGN_VU(vu);
375  continue;
376  }
377  for (BU_LIST_FOR(eu, edgeuse, &lu->down_hd)) {
378  NMG_CK_EDGEUSE(eu);
380  e = eu->e_p;
381  NMG_CK_EDGE(e);
383  if (eu->g.magic_p) switch (*eu->g.magic_p) {
385  NMG_ASSIGN_NEW_INDEX(eu->g.lseg_p);
386  break;
388  NMG_ASSIGN_NEW_INDEX(eu->g.cnurb_p);
389  break;
390  }
391  vu = eu->vu_p;
392  ASSIGN_VU(vu);
393  }
394  }
395  }
396  /* Wire loops in shell */
397  for (BU_LIST_FOR(lu, loopuse, &s->lu_hd)) {
398  NMG_CK_LOOPUSE(lu);
400  l = lu->l_p;
401  NMG_CK_LOOP(l);
403  if (l->lg_p) NMG_ASSIGN_NEW_INDEX(l->lg_p);
404  if (BU_LIST_FIRST_MAGIC(&lu->down_hd) == NMG_VERTEXUSE_MAGIC) {
405  /* Wire loop of Lone vertex */
406  vu = BU_LIST_FIRST(vertexuse, &lu->down_hd);
407  ASSIGN_VU(vu);
408  continue;
409  }
410  for (BU_LIST_FOR(eu, edgeuse, &lu->down_hd)) {
411  NMG_CK_EDGEUSE(eu);
413  e = eu->e_p;
414  NMG_CK_EDGE(e);
416  if (eu->g.magic_p) switch (*eu->g.magic_p) {
418  NMG_ASSIGN_NEW_INDEX(eu->g.lseg_p);
419  break;
421  NMG_ASSIGN_NEW_INDEX(eu->g.cnurb_p);
422  break;
423  }
424  vu = eu->vu_p;
425  ASSIGN_VU(vu);
426  }
427  }
428  /* Wire edges in shell */
429  for (BU_LIST_FOR(eu, edgeuse, &s->eu_hd)) {
430  NMG_CK_EDGEUSE(eu);
432  e = eu->e_p;
433  NMG_CK_EDGE(e);
435  if (eu->g.magic_p) switch (*eu->g.magic_p) {
437  NMG_ASSIGN_NEW_INDEX(eu->g.lseg_p);
438  break;
440  NMG_ASSIGN_NEW_INDEX(eu->g.cnurb_p);
441  break;
442  }
443  vu = eu->vu_p;
444  ASSIGN_VU(vu);
445  }
446  /* Lone vertex in shell */
447  vu = s->vu_p;
448  if (vu) {
449  ASSIGN_VU(vu);
450  }
451  }
452  }
453 #undef ASSIGN_VU
454 
455  if (RTG.NMG_debug & DEBUG_BASIC) {
456  bu_log("nmg_m_reindex() oldmax=%ld, new%ld=>%ld\n",
457  m->maxindex, m->index, newindex);
458  }
459  m->maxindex = newindex;
460 }
461 
462 
463 void
464 nmg_vls_struct_counts(struct bu_vls *str, const struct nmg_struct_counts *ctr)
465 {
466  BU_CK_VLS(str);
467 
468  bu_vls_printf(str, " Actual structure counts:\n");
469  bu_vls_printf(str, "\t%6ld model\n", ctr->model);
470  bu_vls_printf(str, "\t%6ld region\n", ctr->region);
471  bu_vls_printf(str, "\t%6ld region_a\n", ctr->region_a);
472  bu_vls_printf(str, "\t%6ld shell\n", ctr->shell);
473  bu_vls_printf(str, "\t%6ld shell_a\n", ctr->shell_a);
474  bu_vls_printf(str, "\t%6ld face\n", ctr->face);
475  bu_vls_printf(str, "\t%6ld face_g_plane\n", ctr->face_g_plane);
476  bu_vls_printf(str, "\t%6ld face_g_snurb\n", ctr->face_g_snurb);
477  bu_vls_printf(str, "\t%6ld faceuse\n", ctr->faceuse);
478  bu_vls_printf(str, "\t%6ld loopuse\n", ctr->loopuse);
479  bu_vls_printf(str, "\t%6ld loop\n", ctr->loop);
480  bu_vls_printf(str, "\t%6ld loop_g\n", ctr->loop_g);
481  bu_vls_printf(str, "\t%6ld edgeuse\n", ctr->edgeuse);
482  bu_vls_printf(str, "\t%6ld edge\n", ctr->edge);
483  bu_vls_printf(str, "\t%6ld edge_g_lseg\n", ctr->edge_g_lseg);
484  bu_vls_printf(str, "\t%6ld edge_g_cnurb\n", ctr->edge_g_cnurb);
485  bu_vls_printf(str, "\t%6ld vertexuse\n", ctr->vertexuse);
486  bu_vls_printf(str, "\t%6ld vertexuse_a_plane\n", ctr->vertexuse_a_plane);
487  bu_vls_printf(str, "\t%6ld vertexuse_a_cnurb\n", ctr->vertexuse_a_cnurb);
488  bu_vls_printf(str, "\t%6ld vertex\n", ctr->vertex);
489  bu_vls_printf(str, "\t%6ld vertex_g\n", ctr->vertex_g);
490  bu_vls_printf(str, " Abstractions:\n");
491  bu_vls_printf(str, "\t%6ld max_structs\n", ctr->max_structs);
492  bu_vls_printf(str, "\t%6ld face_loops\n", ctr->face_loops);
493  bu_vls_printf(str, "\t%6ld face_edges\n", ctr->face_edges);
494  bu_vls_printf(str, "\t%6ld face_lone_verts\n", ctr->face_lone_verts);
495  bu_vls_printf(str, "\t%6ld wire_loops\n", ctr->wire_loops);
496  bu_vls_printf(str, "\t%6ld wire_loop_edges\n", ctr->wire_loop_edges);
497  bu_vls_printf(str, "\t%6ld wire_edges\n", ctr->wire_edges);
498  bu_vls_printf(str, "\t%6ld wire_lone_verts\n", ctr->wire_lone_verts);
499  bu_vls_printf(str, "\t%6ld shells_of_lone_vert\n", ctr->shells_of_lone_vert);
500 }
501 
502 
503 void
504 nmg_pr_struct_counts(const struct nmg_struct_counts *ctr, const char *str)
505 {
506  struct bu_vls vls = BU_VLS_INIT_ZERO;
507 
508  bu_log("nmg_pr_count(%s)\n", str);
509 
510  nmg_vls_struct_counts(&vls, ctr);
511  bu_log("%s", bu_vls_addr(&vls));
512  bu_vls_free(&vls);
513 }
514 
515 
516 /**
517  * Returns -
518  * Pointer to magic-number/structure-base pointer array,
519  * indexed by nmg structure index.
520  * Caller is responsible for freeing it.
521  */
522 uint32_t **
523 nmg_m_struct_count(register struct nmg_struct_counts *ctr, const struct model *m)
524 {
525  struct nmgregion *r;
526  struct shell *s;
527  struct faceuse *fu;
528  struct face *f;
529  struct loopuse *lu;
530  struct loop *l;
531  struct edgeuse *eu;
532  struct edge *e;
533  struct vertexuse *vu;
534  struct vertex *v;
535  register uint32_t **ptrs;
536 
537 #define NMG_UNIQ_INDEX(_p, _type) \
538  if ((_p)->index > m->maxindex) { \
539  bu_log("%p (%s) has index %ld, m->maxindex=%ld\n", (void *)(_p), \
540  bu_identify_magic(*((uint32_t *)(_p))), (_p)->index, m->maxindex); \
541  bu_bomb("nmg_m_struct_count index overflow\n"); \
542  } \
543  if (ptrs[(_p)->index] == NULL) { \
544  ptrs[(_p)->index] = (uint32_t *)(_p); \
545  ctr->_type++; \
546  }
547 
548 #define UNIQ_VU(_vu) { \
549  NMG_CK_VERTEXUSE(_vu); \
550  NMG_UNIQ_INDEX(_vu, vertexuse); \
551  if (_vu->a.magic_p) switch (*_vu->a.magic_p) { \
552  case NMG_VERTEXUSE_A_PLANE_MAGIC: \
553  NMG_UNIQ_INDEX(_vu->a.plane_p, vertexuse_a_plane); \
554  break; \
555  case NMG_VERTEXUSE_A_CNURB_MAGIC: \
556  NMG_UNIQ_INDEX(_vu->a.cnurb_p, vertexuse_a_cnurb); \
557  break; \
558  } \
559  v = _vu->v_p; \
560  NMG_CK_VERTEX(v); \
561  NMG_UNIQ_INDEX(v, vertex); \
562  if (v->vg_p) { \
563  NMG_CK_VERTEX_G(v->vg_p); \
564  NMG_UNIQ_INDEX(v->vg_p, vertex_g); \
565  } \
566  }
567 
568  NMG_CK_MODEL(m);
569  memset((char *)ctr, 0, sizeof(*ctr));
570 
571  ptrs = (uint32_t **)bu_calloc(m->maxindex+1, sizeof(uint32_t *), "nmg_m_count ptrs[]");
572 
573  NMG_UNIQ_INDEX(m, model);
574  ctr->max_structs = m->maxindex;
575  for (BU_LIST_FOR(r, nmgregion, &m->r_hd)) {
576  NMG_CK_REGION(r);
578  if (r->ra_p) {
579  NMG_CK_REGION_A(r->ra_p);
580  NMG_UNIQ_INDEX(r->ra_p, region_a);
581  }
582  for (BU_LIST_FOR(s, shell, &r->s_hd)) {
583  NMG_CK_SHELL(s);
584  NMG_UNIQ_INDEX(s, shell);
585  if (s->sa_p) {
586  NMG_CK_SHELL_A(s->sa_p);
587  NMG_UNIQ_INDEX(s->sa_p, shell_a);
588  }
589  /* Faces in shell */
590  for (BU_LIST_FOR(fu, faceuse, &s->fu_hd)) {
591  NMG_CK_FACEUSE(fu);
592  NMG_UNIQ_INDEX(fu, faceuse);
593  f = fu->f_p;
594  NMG_CK_FACE(f);
595  NMG_UNIQ_INDEX(f, face);
596  if (f->g.magic_p) switch (*f->g.magic_p) {
598  NMG_UNIQ_INDEX(f->g.plane_p, face_g_plane);
599  break;
601  NMG_UNIQ_INDEX(f->g.snurb_p, face_g_snurb);
602  break;
603  }
604  /* Loops in face */
605  for (BU_LIST_FOR(lu, loopuse, &fu->lu_hd)) {
606  NMG_CK_LOOPUSE(lu);
607  NMG_UNIQ_INDEX(lu, loopuse);
608  l = lu->l_p;
609  NMG_CK_LOOP(l);
610  NMG_UNIQ_INDEX(l, loop);
611  if (l->lg_p) {
612  NMG_CK_LOOP_G(l->lg_p);
613  NMG_UNIQ_INDEX(l->lg_p, loop_g);
614  }
615  if (BU_LIST_FIRST_MAGIC(&lu->down_hd) == NMG_VERTEXUSE_MAGIC) {
616  /* Loop of Lone vertex */
617  ctr->face_lone_verts++;
618  vu = BU_LIST_FIRST(vertexuse, &lu->down_hd);
619  UNIQ_VU(vu);
620  continue;
621  }
622  ctr->face_loops++;
623  for (BU_LIST_FOR(eu, edgeuse, &lu->down_hd)) {
624  ctr->face_edges++;
625  NMG_CK_EDGEUSE(eu);
626  NMG_UNIQ_INDEX(eu, edgeuse);
627  e = eu->e_p;
628  NMG_CK_EDGE(e);
629  NMG_UNIQ_INDEX(e, edge);
630  if (eu->g.magic_p) switch (*eu->g.magic_p) {
632  NMG_UNIQ_INDEX(eu->g.lseg_p, edge_g_lseg);
633  break;
635  NMG_UNIQ_INDEX(eu->g.cnurb_p, edge_g_cnurb);
636  break;
637  }
638  vu = eu->vu_p;
639  UNIQ_VU(vu);
640  }
641  }
642  }
643  /* Wire loops in shell */
644  for (BU_LIST_FOR(lu, loopuse, &s->lu_hd)) {
645  NMG_CK_LOOPUSE(lu);
646  NMG_UNIQ_INDEX(lu, loopuse);
647  l = lu->l_p;
648  NMG_CK_LOOP(l);
649  NMG_UNIQ_INDEX(l, loop);
650  if (l->lg_p) {
651  NMG_CK_LOOP_G(l->lg_p);
652  NMG_UNIQ_INDEX(l->lg_p, loop_g);
653  }
654  if (BU_LIST_FIRST_MAGIC(&lu->down_hd) == NMG_VERTEXUSE_MAGIC) {
655  ctr->wire_lone_verts++;
656  /* Wire loop of Lone vertex */
657  vu = BU_LIST_FIRST(vertexuse, &lu->down_hd);
658  UNIQ_VU(vu);
659  continue;
660  }
661  ctr->wire_loops++;
662  for (BU_LIST_FOR(eu, edgeuse, &lu->down_hd)) {
663  NMG_CK_EDGEUSE(eu);
664  NMG_UNIQ_INDEX(eu, edgeuse);
665  e = eu->e_p;
666  NMG_CK_EDGE(e);
667  NMG_UNIQ_INDEX(e, edge);
668  if (eu->g.magic_p) switch (*eu->g.magic_p) {
670  NMG_UNIQ_INDEX(eu->g.lseg_p, edge_g_lseg);
671  break;
673  NMG_UNIQ_INDEX(eu->g.cnurb_p, edge_g_cnurb);
674  break;
675  }
676  vu = eu->vu_p;
677  UNIQ_VU(vu);
678  ctr->wire_loop_edges++;
679  }
680  }
681  /* Wire edges in shell */
682  for (BU_LIST_FOR(eu, edgeuse, &s->eu_hd)) {
683  NMG_CK_EDGEUSE(eu);
684  ctr->wire_edges++;
685  NMG_UNIQ_INDEX(eu, edgeuse);
686  e = eu->e_p;
687  NMG_CK_EDGE(e);
688  NMG_UNIQ_INDEX(e, edge);
689  if (eu->g.magic_p) switch (*eu->g.magic_p) {
691  NMG_UNIQ_INDEX(eu->g.lseg_p, edge_g_lseg);
692  break;
694  NMG_UNIQ_INDEX(eu->g.cnurb_p, edge_g_cnurb);
695  break;
696  }
697  vu = eu->vu_p;
698  UNIQ_VU(vu);
699  }
700  /* Lone vertex in shell */
701  vu = s->vu_p;
702  if (vu) {
703  ctr->shells_of_lone_vert++;
704  UNIQ_VU(vu);
705  }
706  }
707  }
708  /* Caller must free them */
709  return ptrs;
710 #undef UNIQ_VU
711 }
712 
713 
714 /**
715  *
716  * Count 'em up, and print 'em out.
717  */
718 void
719 nmg_pr_m_struct_counts(const struct model *m, const char *str)
720 {
721  struct nmg_struct_counts cnts;
722  uint32_t **tab;
723 
724  NMG_CK_MODEL(m);
725 
726  tab = nmg_m_struct_count(&cnts, m);
727  bu_free((void *)tab, "nmg_m_struct_count");
728  nmg_pr_struct_counts(&cnts, str);
729 }
730 
731 
732 /**
733  * Combine two NMG model trees into one single NMG model. The
734  * first model inherits the nmgregions of the second. The second
735  * model pointer is freed before return.
736  */
737 void
738 nmg_merge_models(struct model *m1, struct model *m2)
739 {
740  struct nmgregion *r;
741 
742  NMG_CK_MODEL(m1);
743  NMG_CK_MODEL(m2);
744 
745  /* first reorder the first model to "compress" the
746  * number space if possible.
747  */
748  nmg_m_reindex(m1, 0);
749 
750  if (m1 == m2) /* nothing to do */
751  return;
752 
753  /* now re-order the second model starting with an index number
754  * of m1->maxindex.
755  *
756  * We might get away with using m1->maxindex-1, since the first
757  * value is assigned to the second model structure, and we will
758  * shortly be freeing the second model struct.
759  */
760 
761  nmg_m_reindex(m2, m1->maxindex);
762  m1->maxindex = m2->maxindex; /* big enough for both */
763 
764  /* Rehome all the regions in m2, and move them from m2 to m1 */
765  for (BU_LIST_FOR(r, nmgregion, &(m2->r_hd))) {
766  NMG_CK_REGION(r);
767  r->m_p = m1;
768  }
769  BU_LIST_APPEND_LIST(&(m1->r_hd), &(m2->r_hd));
770 
771  /* If there are any manifold tables, when the models are
772  * merged they become invalid and need to be regenerated.
773  * To avoid confusion, free them here so it is known they
774  * need to be regenerated.
775  */
776  if (m1->manifolds) {
777  bu_free((char *)m1->manifolds, "free manifolds table");
778  m1->manifolds = (char *)NULL;
779  }
780  if (m2->manifolds) {
781  bu_free((char *)m2->manifolds, "free manifolds table");
782  m2->manifolds = (char *)NULL;
783  }
784 
785  FREE_MODEL(m2);
786 }
787 
788 
789 #define CHECK_INDEX(_p) if ((_p)->index > maxindex) maxindex = (_p)->index
790 #define CHECK_VU_INDEX(_vu) {\
791  NMG_CK_VERTEXUSE(_vu); \
792  CHECK_INDEX(_vu); \
793  if (_vu->a.magic_p) switch (*_vu->a.magic_p) { \
794  case NMG_VERTEXUSE_A_PLANE_MAGIC: \
795  CHECK_INDEX(_vu->a.plane_p); \
796  break; \
797  case NMG_VERTEXUSE_A_CNURB_MAGIC: \
798  CHECK_INDEX(_vu->a.cnurb_p); \
799  break; \
800  } \
801  v = _vu->v_p; \
802  NMG_CK_VERTEX(v); \
803  CHECK_INDEX(v); \
804  if (v->vg_p) CHECK_INDEX(v->vg_p); \
805  }
806 
807 long
808 nmg_find_max_index(const struct model *m)
809 {
810  long maxindex=0;
811  struct nmgregion *r;
812  struct shell *s;
813  struct faceuse *fu;
814  struct face *f;
815  struct loopuse *lu;
816  struct loop *l;
817  register struct edgeuse *eu;
818  struct edge *e;
819  register struct vertexuse *vu;
820  struct vertex *v;
821 
822  for (BU_LIST_FOR(r, nmgregion, &m->r_hd)) {
823  NMG_CK_REGION(r);
824  CHECK_INDEX(r);
825  if (r->ra_p) CHECK_INDEX(r->ra_p);
826  for (BU_LIST_FOR(s, shell, &r->s_hd)) {
827  NMG_CK_SHELL(s);
828  CHECK_INDEX(s);
829  if (s->sa_p) CHECK_INDEX(s->sa_p);
830  /* Faces in shell */
831  for (BU_LIST_FOR(fu, faceuse, &s->fu_hd)) {
832  NMG_CK_FACEUSE(fu);
833  CHECK_INDEX(fu);
834  f = fu->f_p;
835  NMG_CK_FACE(f);
836  CHECK_INDEX(f);
837  if (f->g.plane_p) switch (*f->g.magic_p) {
839  CHECK_INDEX(f->g.plane_p);
840  break;
842  CHECK_INDEX(f->g.snurb_p);
843  break;
844  }
845  /* Loops in face */
846  for (BU_LIST_FOR(lu, loopuse, &fu->lu_hd)) {
847  NMG_CK_LOOPUSE(lu);
848  CHECK_INDEX(lu);
849  l = lu->l_p;
850  NMG_CK_LOOP(l);
851  CHECK_INDEX(l);
852  if (l->lg_p) CHECK_INDEX(l->lg_p);
853  if (BU_LIST_FIRST_MAGIC(&lu->down_hd) == NMG_VERTEXUSE_MAGIC) {
854  /* Loop of Lone vertex */
855  vu = BU_LIST_FIRST(vertexuse, &lu->down_hd);
856  CHECK_VU_INDEX(vu);
857  continue;
858  }
859  for (BU_LIST_FOR(eu, edgeuse, &lu->down_hd)) {
860  NMG_CK_EDGEUSE(eu);
861  CHECK_INDEX(eu);
862  e = eu->e_p;
863  NMG_CK_EDGE(e);
864  CHECK_INDEX(e);
865  if (eu->g.magic_p) switch (*eu->g.magic_p) {
867  CHECK_INDEX(eu->g.lseg_p);
868  break;
870  CHECK_INDEX(eu->g.cnurb_p);
871  break;
872  }
873  vu = eu->vu_p;
874  CHECK_VU_INDEX(vu);
875  }
876  }
877  }
878  /* Wire loops in shell */
879  for (BU_LIST_FOR(lu, loopuse, &s->lu_hd)) {
880  NMG_CK_LOOPUSE(lu);
881  CHECK_INDEX(lu);
882  l = lu->l_p;
883  NMG_CK_LOOP(l);
884  CHECK_INDEX(l);
885  if (l->lg_p) CHECK_INDEX(l->lg_p);
886  if (BU_LIST_FIRST_MAGIC(&lu->down_hd) == NMG_VERTEXUSE_MAGIC) {
887  /* Wire loop of Lone vertex */
888  vu = BU_LIST_FIRST(vertexuse, &lu->down_hd);
889  CHECK_VU_INDEX(vu);
890  continue;
891  }
892  for (BU_LIST_FOR(eu, edgeuse, &lu->down_hd)) {
893  NMG_CK_EDGEUSE(eu);
894  CHECK_INDEX(eu);
895  e = eu->e_p;
896  NMG_CK_EDGE(e);
897  CHECK_INDEX(e);
898  if (eu->g.magic_p) switch (*eu->g.magic_p) {
900  CHECK_INDEX(eu->g.lseg_p);
901  break;
903  CHECK_INDEX(eu->g.cnurb_p);
904  break;
905  }
906  vu = eu->vu_p;
907  CHECK_VU_INDEX(vu);
908  }
909  }
910  /* Wire edges in shell */
911  for (BU_LIST_FOR(eu, edgeuse, &s->eu_hd)) {
912  NMG_CK_EDGEUSE(eu);
913  CHECK_INDEX(eu);
914  e = eu->e_p;
915  NMG_CK_EDGE(e);
916  CHECK_INDEX(e);
917  if (eu->g.magic_p) switch (*eu->g.magic_p) {
919  CHECK_INDEX(eu->g.lseg_p);
920  break;
922  CHECK_INDEX(eu->g.cnurb_p);
923  break;
924  }
925  vu = eu->vu_p;
926  CHECK_VU_INDEX(vu);
927  }
928  /* Lone vertex in shell */
929  vu = s->vu_p;
930  if (vu) {
931  CHECK_VU_INDEX(vu);
932  }
933  }
934  }
935  return maxindex;
936 }
937 
938 
939 /*
940  * Local Variables:
941  * mode: C
942  * tab-width: 8
943  * indent-tabs-mode: t
944  * c-file-style: "stroustrup"
945  * End:
946  * ex: shiftwidth=4 tabstop=8
947  */
void nmg_m_set_high_bit(struct model *m)
Definition: nmg_index.c:145
#define NMG_MODEL_MAGIC
Definition: magic.h:133
#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
#define ASSIGN_VU(_vu)
#define NMG_EDGE_MAGIC
Definition: magic.h:123
#define NMG_SHELL_MAGIC
Definition: magic.h:142
void nmg_pr_struct_counts(const struct nmg_struct_counts *ctr, const char *str)
Definition: nmg_index.c:504
#define NMG_LOOP_G_MAGIC
Definition: magic.h:131
#define NMG_VERTEX_MAGIC
Definition: magic.h:147
#define NMG_FACE_G_SNURB_MAGIC
Definition: magic.h:126
if lu s
Definition: nmg_mod.c:3860
#define NMG_ASSIGN_NEW_INDEX(_p)
Definition: nmg_index.c:111
lu
Definition: nmg_mod.c:3855
int nmg_index_of_struct(register const uint32_t *p)
Definition: nmg_index.c:49
Header file for the BRL-CAD common definitions.
#define NMG_UNIQ_INDEX(_p, _type)
void nmg_vls_struct_counts(struct bu_vls *str, const struct nmg_struct_counts *ctr)
Definition: nmg_index.c:464
#define NMG_LOOPUSE_MAGIC
Definition: magic.h:130
NMG_CK_LOOPUSE(lu)
void bu_vls_free(struct bu_vls *vp)
Definition: vls.c:248
#define NMG_EDGEUSE2_MAGIC
Definition: magic.h:119
#define BU_CK_VLS(_vp)
Definition: vls.h:69
void * memset(void *s, int c, size_t n)
#define CHECK_INDEX(_p)
Definition: nmg_index.c:789
uint32_t ** nmg_m_struct_count(register struct nmg_struct_counts *ctr, const struct model *m)
Definition: nmg_index.c:523
#define NMG_LOOP_MAGIC
Definition: magic.h:132
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 * bu_calloc(size_t nelem, size_t elsize, const char *str)
Definition: malloc.c:321
#define NMG_SHELL_A_MAGIC
Definition: magic.h:141
void nmg_pr_m_struct_counts(const struct model *m, const char *str)
Definition: nmg_index.c:719
#define NMG_REGION_MAGIC
Definition: magic.h:137
#define BU_LIST_FIRST_MAGIC(hp)
Definition: list.h:416
char * bu_vls_addr(const struct bu_vls *vp)
Definition: vls.c:111
#define NMG_VERTEXUSE_MAGIC
Definition: magic.h:145
#define NMG_VERTEXUSE_A_CNURB_MAGIC
Definition: magic.h:143
#define BU_LIST_MAIN_PTR(_type, _ptr2, _name2)
Definition: list.h:470
#define NMG_FACE_G_PLANE_MAGIC
Definition: magic.h:125
#define NMG_EDGE_G_LSEG_MAGIC
Definition: magic.h:122
#define CHECK_VU_INDEX(_vu)
Definition: nmg_index.c:790
#define NMG_EDGE_G_CNURB_MAGIC
Definition: magic.h:121
void nmg_m_reindex(struct model *m, register long int newindex)
Definition: nmg_index.c:298
#define NMG_MARK_INDEX(_p)
Definition: nmg_index.c:109
#define UNIQ_VU(_vu)
eu1 up magic_p
Definition: nmg_mod.c:3915
void bu_vls_printf(struct bu_vls *vls, const char *fmt,...) _BU_ATTR_PRINTF23
Definition: vls.c:694
#define NMG_VERTEXUSE_A_PLANE_MAGIC
Definition: magic.h:144
#define NMG_REGION_A_MAGIC
Definition: magic.h:136
void bu_free(void *ptr, const char *str)
Definition: malloc.c:328
#define NMG_VERTEX_G_MAGIC
Definition: magic.h:146
NMG_CK_SHELL(s)
#define MARK_VU(_vu)
#define BU_VLS_INIT_ZERO
Definition: vls.h:84
#define BU_LIST_HEAD_MAGIC
Definition: magic.h:56
#define NMG_FACEUSE_MAGIC
Definition: magic.h:124
Definition: vls.h:56
void bu_bomb(const char *str) _BU_ATTR_NORETURN
Definition: bomb.c:91
long nmg_find_max_index(const struct model *m)
Definition: nmg_index.c:808
#define BU_LIST_APPEND_LIST(dest_hp, src_hp)
Definition: list.h:281
#define BU_LIST_FIRST(structure, hp)
Definition: list.h:312
void nmg_merge_models(struct model *m1, struct model *m2)
Definition: nmg_index.c:738
struct rt_g RTG
Definition: globals.c:39