nmg_index.c

Go to the documentation of this file.
00001 /*                     N M G _ I N D E X . C
00002  * BRL-CAD
00003  *
00004  * Copyright (c) 1990-2006 United States Government as represented by
00005  * the U.S. Army Research Laboratory.
00006  *
00007  * This library is free software; you can redistribute it and/or
00008  * modify it under the terms of the GNU Lesser General Public License
00009  * as published by the Free Software Foundation; either version 2 of
00010  * the License, or (at your option) any later version.
00011  *
00012  * This library is distributed in the hope that it will be useful, but
00013  * WITHOUT ANY WARRANTY; without even the implied warranty of
00014  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
00015  * Library General Public License for more details.
00016  *
00017  * You should have received a copy of the GNU Lesser General Public
00018  * License along with this file; see the file named COPYING for more
00019  * information.
00020  */
00021 
00022 /** @addtogroup nmg */
00023 
00024 /*@{*/
00025 /** @file nmg_index.c
00026  *  Handle counting and re-indexing of NMG data structures.
00027  *
00028  *  Authors -
00029  *      Michael John Muuss
00030  *      Lee A. Butler
00031  *
00032  *  Source -
00033  *      SECAD/VLD Computing Consortium, Bldg 394
00034  *      The U. S. Army Ballistic Research Laboratory
00035  *      Aberdeen Proving Ground, Maryland  21005
00036  *
00037  */
00038 /*@}*/
00039 
00040 #ifndef lint
00041 static const char RCSnmg_index[] = "@(#)$Header: /cvsroot/brlcad/brlcad/src/librt/nmg_index.c,v 14.12 2006/09/16 02:04:25 lbutler Exp $ (BRL)";
00042 #endif
00043 
00044 #include "common.h"
00045 
00046 #include <stddef.h>
00047 #include <stdio.h>
00048 #include <string.h>
00049 #include <math.h>
00050 
00051 #include "machine.h"
00052 #include "vmath.h"
00053 #include "nmg.h"
00054 #include "raytrace.h"
00055 
00056 /**
00057  *                      N M G _ I N D E X _ O F _ S T R U C T
00058  *
00059  *  Return the structure index number of an arbitrary NMG structure.
00060  *
00061  *  Returns -
00062  *      >=0     index number
00063  *       -1     pointed at struct bu_list embedded within NMG structure.
00064  *       -2     error:  unknown magic number
00065  */
00066 int
00067 nmg_index_of_struct(register const long int *p)
00068 {
00069         switch(*p)  {
00070         case NMG_MODEL_MAGIC:
00071                 return ((struct model *)p)->index;
00072         case NMG_REGION_MAGIC:
00073                 return ((struct nmgregion *)p)->index;
00074         case NMG_REGION_A_MAGIC:
00075                 return ((struct nmgregion_a *)p)->index;
00076         case NMG_SHELL_MAGIC:
00077                 return ((struct shell *)p)->index;
00078         case NMG_SHELL_A_MAGIC:
00079                 return ((struct shell_a *)p)->index;
00080         case NMG_FACEUSE_MAGIC:
00081                 return ((struct faceuse *)p)->index;
00082         case NMG_FACE_MAGIC:
00083                 return ((struct face *)p)->index;
00084         case NMG_FACE_G_PLANE_MAGIC:
00085                 return ((struct face_g_plane *)p)->index;
00086         case NMG_FACE_G_SNURB_MAGIC:
00087                 return ((struct face_g_snurb *)p)->index;
00088         case NMG_LOOPUSE_MAGIC:
00089                 return ((struct loopuse *)p)->index;
00090         case NMG_LOOP_MAGIC:
00091                 return ((struct loop *)p)->index;
00092         case NMG_LOOP_G_MAGIC:
00093                 return ((struct loop_g *)p)->index;
00094         case NMG_EDGEUSE_MAGIC:
00095                 return ((struct edgeuse *)p)->index;
00096         case NMG_EDGEUSE2_MAGIC:
00097                 /* Points to l2 inside edgeuse */
00098                 return BU_LIST_MAIN_PTR(edgeuse, p, l2)->index;
00099         case NMG_EDGE_MAGIC:
00100                 return ((struct edge *)p)->index;
00101         case NMG_EDGE_G_LSEG_MAGIC:
00102                 return ((struct edge_g_lseg *)p)->index;
00103         case NMG_EDGE_G_CNURB_MAGIC:
00104                 return ((struct edge_g_cnurb *)p)->index;
00105         case NMG_VERTEXUSE_MAGIC:
00106                 return ((struct vertexuse *)p)->index;
00107         case NMG_VERTEXUSE_A_PLANE_MAGIC:
00108                 return ((struct vertexuse_a_plane *)p)->index;
00109         case NMG_VERTEXUSE_A_CNURB_MAGIC:
00110                 return ((struct vertexuse_a_cnurb *)p)->index;
00111         case NMG_VERTEX_MAGIC:
00112                 return ((struct vertex *)p)->index;
00113         case NMG_VERTEX_G_MAGIC:
00114                 return ((struct vertex_g *)p)->index;
00115         case BU_LIST_HEAD_MAGIC:
00116                 /* indicate special list head encountered */
00117                 return -1;
00118         }
00119         /* default */
00120         bu_log("nmg_index_of_struct: magicp = x%x, magic = x%x\n", p, *p);
00121         return -2;      /* indicate error */
00122 }
00123 
00124 #define NMG_HIGH_BIT    0x80000000
00125 
00126 #define NMG_MARK_INDEX(_p)      ((_p)->index |= NMG_HIGH_BIT)
00127 
00128 #define NMG_ASSIGN_NEW_INDEX(_p)        \
00129         { if( ((_p)->index & NMG_HIGH_BIT) != 0 ) \
00130                 (_p)->index = newindex++; }
00131 
00132 /**
00133  *                      N M G _ M A R K _ E D G E _ G
00134  *
00135  *  Helper routine
00136  */
00137 static void
00138 nmg_mark_edge_g(long int *magic_p)
00139 {
00140         if( !magic_p )  rt_bomb("nmg_mark_edge_g bad magic\n");
00141         switch( *magic_p )  {
00142         case NMG_EDGE_G_LSEG_MAGIC:
00143                 {
00144                         struct edge_g_lseg *lseg = (struct edge_g_lseg *)magic_p;
00145                         NMG_MARK_INDEX(lseg);
00146                         return;
00147                 }
00148         case NMG_EDGE_G_CNURB_MAGIC:
00149                 {
00150                         struct edge_g_cnurb *cnurb = (struct edge_g_cnurb *)magic_p;
00151                         NMG_MARK_INDEX(cnurb);
00152                         return;
00153                 }
00154         }
00155         rt_bomb("nmg_mark_edge_g() unknown magic\n");
00156 }
00157 
00158 /**
00159  *                      N M G _ M _ S E T _ H I G H _ B I T
00160  *
00161  *  First pass:  just set the high bit on all index words
00162  *
00163  *  This is a separate function largely for the benefit of global optimizers,
00164  *  which tended to blow their brains out on such a large subroutine.
00165  */
00166 void
00167 nmg_m_set_high_bit(struct model *m)
00168 {
00169         struct nmgregion        *r;
00170         struct shell            *s;
00171         struct  faceuse         *fu;
00172         struct face             *f;
00173         struct loopuse          *lu;
00174         struct loop             *l;
00175         register struct edgeuse         *eu;
00176         struct edge                     *e;
00177         register struct vertexuse       *vu;
00178 
00179 #define MARK_VU(_vu)    { \
00180         struct vertex   *v; \
00181         NMG_CK_VERTEXUSE(_vu); \
00182         NMG_MARK_INDEX(_vu); \
00183         if(_vu->a.magic_p) switch(*_vu->a.magic_p)  { \
00184         case NMG_VERTEXUSE_A_PLANE_MAGIC: \
00185                 NMG_MARK_INDEX(_vu->a.plane_p); \
00186                 break; \
00187         case NMG_VERTEXUSE_A_CNURB_MAGIC: \
00188                 NMG_MARK_INDEX(_vu->a.cnurb_p); \
00189                 break; \
00190         } \
00191         v = _vu->v_p; \
00192         NMG_CK_VERTEX(v); \
00193         NMG_MARK_INDEX(v); \
00194         if(v->vg_p)  { \
00195                 NMG_CK_VERTEX_G(v->vg_p); \
00196                 NMG_MARK_INDEX(v->vg_p); \
00197         } \
00198     }
00199 
00200         NMG_CK_MODEL(m);
00201         NMG_MARK_INDEX(m);
00202 
00203         for( BU_LIST_FOR( r, nmgregion, &m->r_hd ) )  {
00204                 NMG_CK_REGION(r);
00205                 NMG_MARK_INDEX(r);
00206                 if( r->ra_p )  {
00207                         NMG_CK_REGION_A(r->ra_p);
00208                         NMG_MARK_INDEX(r->ra_p);
00209                 }
00210                 for( BU_LIST_FOR( s, shell, &r->s_hd ) )  {
00211                         NMG_CK_SHELL(s);
00212                         NMG_MARK_INDEX(s);
00213                         if( s->sa_p )  {
00214                                 NMG_CK_SHELL_A(s->sa_p);
00215                                 NMG_MARK_INDEX(s->sa_p);
00216                         }
00217                         /* Faces in shell */
00218                         for( BU_LIST_FOR( fu, faceuse, &s->fu_hd ) )  {
00219                                 NMG_CK_FACEUSE(fu);
00220                                 NMG_MARK_INDEX(fu);
00221                                 f = fu->f_p;
00222                                 NMG_CK_FACE(f);
00223                                 NMG_MARK_INDEX(f);
00224                                 if(f->g.magic_p) switch( *f->g.magic_p )  {
00225                                 case NMG_FACE_G_PLANE_MAGIC:
00226                                         NMG_MARK_INDEX(f->g.plane_p);
00227                                         break;
00228                                 case NMG_FACE_G_SNURB_MAGIC:
00229                                         NMG_MARK_INDEX(f->g.snurb_p);
00230                                         break;
00231                                 }
00232                                 /* Loops in face */
00233                                 for( BU_LIST_FOR( lu, loopuse, &fu->lu_hd ) )  {
00234                                         NMG_CK_LOOPUSE(lu);
00235                                         NMG_MARK_INDEX(lu);
00236                                         l = lu->l_p;
00237                                         NMG_CK_LOOP(l);
00238                                         NMG_MARK_INDEX(l);
00239                                         if( l->lg_p )  {
00240                                                 NMG_CK_LOOP_G(l->lg_p);
00241                                                 NMG_MARK_INDEX(l->lg_p);
00242                                         }
00243                                         if( BU_LIST_FIRST_MAGIC(&lu->down_hd) == NMG_VERTEXUSE_MAGIC )  {
00244                                                 /* Loop of Lone vertex */
00245                                                 vu = BU_LIST_FIRST( vertexuse, &lu->down_hd );
00246                                                 MARK_VU(vu);
00247                                                 continue;
00248                                         }
00249                                         for( BU_LIST_FOR( eu, edgeuse, &lu->down_hd ) )  {
00250                                                 NMG_CK_EDGEUSE(eu);
00251                                                 NMG_MARK_INDEX(eu);
00252                                                 e = eu->e_p;
00253                                                 NMG_CK_EDGE(e);
00254                                                 NMG_MARK_INDEX(e);
00255                                                 if(eu->g.magic_p) nmg_mark_edge_g( eu->g.magic_p );
00256                                                 vu = eu->vu_p;
00257                                                 MARK_VU(vu);
00258                                         }
00259                                 }
00260                         }
00261                         /* Wire loops in shell */
00262                         for( BU_LIST_FOR( lu, loopuse, &s->lu_hd ) )  {
00263                                 NMG_CK_LOOPUSE(lu);
00264                                 NMG_MARK_INDEX(lu);
00265                                 l = lu->l_p;
00266                                 NMG_CK_LOOP(l);
00267                                 NMG_MARK_INDEX(l);
00268                                 if( l->lg_p )  {
00269                                         NMG_CK_LOOP_G(l->lg_p);
00270                                         NMG_MARK_INDEX(l->lg_p);
00271                                 }
00272                                 if( BU_LIST_FIRST_MAGIC(&lu->down_hd) == NMG_VERTEXUSE_MAGIC )  {
00273                                         /* Wire loop of Lone vertex */
00274                                         vu = BU_LIST_FIRST( vertexuse, &lu->down_hd );
00275                                         MARK_VU(vu);
00276                                         continue;
00277                                 }
00278                                 for( BU_LIST_FOR( eu, edgeuse, &lu->down_hd ) )  {
00279                                         NMG_CK_EDGEUSE(eu);
00280                                         NMG_MARK_INDEX(eu);
00281                                         e = eu->e_p;
00282                                         NMG_CK_EDGE(e);
00283                                         NMG_MARK_INDEX(e);
00284                                         if(eu->g.magic_p) nmg_mark_edge_g( eu->g.magic_p );
00285                                         vu = eu->vu_p;
00286                                         MARK_VU(vu);
00287                                 }
00288                         }
00289                         /* Wire edges in shell */
00290                         for( BU_LIST_FOR( eu, edgeuse, &s->eu_hd ) )  {
00291                                 NMG_CK_EDGEUSE(eu);
00292                                 NMG_MARK_INDEX(eu);
00293                                 e = eu->e_p;
00294                                 NMG_CK_EDGE(e);
00295                                 NMG_MARK_INDEX(e);
00296                                 if(eu->g.magic_p) nmg_mark_edge_g( eu->g.magic_p );
00297                                 vu = eu->vu_p;
00298                                 MARK_VU(vu);
00299                         }
00300                         /* Lone vertex in shell */
00301                         if( (vu = s->vu_p) )  {
00302                                 MARK_VU(vu);
00303                         }
00304                 }
00305         }
00306 #undef MARK_VU
00307 }
00308 
00309 /**
00310  *                      N M G _ M _ R E I N D E X
00311  *
00312  *  Reassign index numbers to all the data structures in a model.
00313  *  The model structure will get index 0, all others will be sequentially
00314  *  assigned after that.
00315  *
00316  *  Because the first pass has done extensive error checking,
00317  *  the second pass can do less.
00318  */
00319 void
00320 nmg_m_reindex(struct model *m, register long int newindex)
00321 {
00322         struct nmgregion        *r;
00323         struct shell            *s;
00324         struct faceuse          *fu;
00325         struct face             *f;
00326         struct loopuse          *lu;
00327         struct loop             *l;
00328         register struct edgeuse         *eu;
00329         struct edge                     *e;
00330         register struct vertexuse       *vu;
00331         struct vertex                   *v;
00332 
00333 #define ASSIGN_VU(_vu)  { \
00334                 NMG_CK_VERTEXUSE(_vu); \
00335                 NMG_ASSIGN_NEW_INDEX(_vu); \
00336                 if(_vu->a.magic_p)  switch(*_vu->a.magic_p)  { \
00337                 case NMG_VERTEXUSE_A_PLANE_MAGIC: \
00338                         NMG_ASSIGN_NEW_INDEX(_vu->a.plane_p); \
00339                         break; \
00340                 case NMG_VERTEXUSE_A_CNURB_MAGIC: \
00341                         NMG_ASSIGN_NEW_INDEX(_vu->a.cnurb_p); \
00342                         break; \
00343                 } \
00344                 v = _vu->v_p; \
00345                 NMG_CK_VERTEX(v); \
00346                 NMG_ASSIGN_NEW_INDEX(v); \
00347                 if(v->vg_p) NMG_ASSIGN_NEW_INDEX(v->vg_p); \
00348         }
00349 
00350         NMG_CK_MODEL(m);
00351         if( m->index != 0 )  bu_log("nmg_m_reindex() m->index=%d\n", m->index);
00352         if ( newindex < 0 )  bu_log("nmg_m_reindex() newindex(%ld) < 0\n", newindex);
00353 
00354         /* First pass:  set high bits */
00355         nmg_m_set_high_bit( m );
00356 
00357         /*
00358          *  Second pass:  assign new index number
00359          */
00360 
00361         NMG_ASSIGN_NEW_INDEX(m);
00362         for( BU_LIST_FOR( r, nmgregion, &m->r_hd ) )  {
00363                 NMG_CK_REGION(r);
00364                 NMG_ASSIGN_NEW_INDEX(r);
00365                 if( r->ra_p )  NMG_ASSIGN_NEW_INDEX(r->ra_p);
00366                 for( BU_LIST_FOR( s, shell, &r->s_hd ) )  {
00367                         NMG_CK_SHELL(s);
00368                         NMG_ASSIGN_NEW_INDEX(s);
00369                         if( s->sa_p )  NMG_ASSIGN_NEW_INDEX(s->sa_p);
00370                         /* Faces in shell */
00371                         for( BU_LIST_FOR( fu, faceuse, &s->fu_hd ) )  {
00372                                 NMG_CK_FACEUSE(fu);
00373                                 NMG_ASSIGN_NEW_INDEX(fu);
00374                                 f = fu->f_p;
00375                                 NMG_CK_FACE(f);
00376                                 NMG_ASSIGN_NEW_INDEX(f);
00377                                 if( f->g.plane_p ) switch( *f->g.magic_p )  {
00378                                 case NMG_FACE_G_PLANE_MAGIC:
00379                                         NMG_ASSIGN_NEW_INDEX(f->g.plane_p);
00380                                         break;
00381                                 case NMG_FACE_G_SNURB_MAGIC:
00382                                         NMG_ASSIGN_NEW_INDEX(f->g.snurb_p);
00383                                         break;
00384                                 }
00385                                 /* Loops in face */
00386                                 for( BU_LIST_FOR( lu, loopuse, &fu->lu_hd ) )  {
00387                                         NMG_CK_LOOPUSE(lu);
00388                                         NMG_ASSIGN_NEW_INDEX(lu);
00389                                         l = lu->l_p;
00390                                         NMG_CK_LOOP(l);
00391                                         NMG_ASSIGN_NEW_INDEX(l);
00392                                         if( l->lg_p )  NMG_ASSIGN_NEW_INDEX(l->lg_p);
00393                                         if( BU_LIST_FIRST_MAGIC(&lu->down_hd) == NMG_VERTEXUSE_MAGIC )  {
00394                                                 /* Loop of Lone vertex */
00395                                                 vu = BU_LIST_FIRST( vertexuse, &lu->down_hd );
00396                                                 ASSIGN_VU(vu);
00397                                                 continue;
00398                                         }
00399                                         for( BU_LIST_FOR( eu, edgeuse, &lu->down_hd ) )  {
00400                                                 NMG_CK_EDGEUSE(eu);
00401                                                 NMG_ASSIGN_NEW_INDEX(eu);
00402                                                 e = eu->e_p;
00403                                                 NMG_CK_EDGE(e);
00404                                                 NMG_ASSIGN_NEW_INDEX(e);
00405                                                 if( eu->g.magic_p ) switch(*eu->g.magic_p)  {
00406                                                 case NMG_EDGE_G_LSEG_MAGIC:
00407                                                         NMG_ASSIGN_NEW_INDEX(eu->g.lseg_p);
00408                                                         break;
00409                                                 case NMG_EDGE_G_CNURB_MAGIC:
00410                                                         NMG_ASSIGN_NEW_INDEX(eu->g.cnurb_p);
00411                                                         break;
00412                                                 }
00413                                                 vu = eu->vu_p;
00414                                                 ASSIGN_VU(vu);
00415                                         }
00416                                 }
00417                         }
00418                         /* Wire loops in shell */
00419                         for( BU_LIST_FOR( lu, loopuse, &s->lu_hd ) )  {
00420                                 NMG_CK_LOOPUSE(lu);
00421                                 NMG_ASSIGN_NEW_INDEX(lu);
00422                                 l = lu->l_p;
00423                                 NMG_CK_LOOP(l);
00424                                 NMG_ASSIGN_NEW_INDEX(l);
00425                                 if( l->lg_p )  NMG_ASSIGN_NEW_INDEX(l->lg_p);
00426                                 if( BU_LIST_FIRST_MAGIC(&lu->down_hd) == NMG_VERTEXUSE_MAGIC )  {
00427                                         /* Wire loop of Lone vertex */
00428                                         vu = BU_LIST_FIRST( vertexuse, &lu->down_hd );
00429                                         ASSIGN_VU(vu);
00430                                         continue;
00431                                 }
00432                                 for( BU_LIST_FOR( eu, edgeuse, &lu->down_hd ) )  {
00433                                         NMG_CK_EDGEUSE(eu);
00434                                         NMG_ASSIGN_NEW_INDEX(eu);
00435                                         e = eu->e_p;
00436                                         NMG_CK_EDGE(e);
00437                                         NMG_ASSIGN_NEW_INDEX(e);
00438                                         if( eu->g.magic_p ) switch(*eu->g.magic_p)  {
00439                                         case NMG_EDGE_G_LSEG_MAGIC:
00440                                                 NMG_ASSIGN_NEW_INDEX(eu->g.lseg_p);
00441                                                 break;
00442                                         case NMG_EDGE_G_CNURB_MAGIC:
00443                                                 NMG_ASSIGN_NEW_INDEX(eu->g.cnurb_p);
00444                                                 break;
00445                                         }
00446                                         vu = eu->vu_p;
00447                                         ASSIGN_VU(vu);
00448                                 }
00449                         }
00450                         /* Wire edges in shell */
00451                         for( BU_LIST_FOR( eu, edgeuse, &s->eu_hd ) )  {
00452                                 NMG_CK_EDGEUSE(eu);
00453                                 NMG_ASSIGN_NEW_INDEX(eu);
00454                                 e = eu->e_p;
00455                                 NMG_CK_EDGE(e);
00456                                 NMG_ASSIGN_NEW_INDEX(e);
00457                                 if( eu->g.magic_p ) switch(*eu->g.magic_p)  {
00458                                 case NMG_EDGE_G_LSEG_MAGIC:
00459                                         NMG_ASSIGN_NEW_INDEX(eu->g.lseg_p);
00460                                         break;
00461                                 case NMG_EDGE_G_CNURB_MAGIC:
00462                                         NMG_ASSIGN_NEW_INDEX(eu->g.cnurb_p);
00463                                         break;
00464                                 }
00465                                 vu = eu->vu_p;
00466                                 ASSIGN_VU(vu);
00467                         }
00468                         /* Lone vertex in shell */
00469                         if( (vu = s->vu_p) )  {
00470                                 ASSIGN_VU(vu);
00471                         }
00472                 }
00473         }
00474 #undef ASSIGN_VU
00475 
00476         if( rt_g.NMG_debug & DEBUG_BASIC )  {
00477                  bu_log("nmg_m_reindex() oldmax=%d, new%d=>%d\n",
00478                         m->maxindex, m->index, newindex );
00479         }
00480         m->maxindex = newindex;
00481 }
00482 
00483 /**
00484  *                      N M G _ V L S _ S T R U C T _ C O U N T S
00485  *
00486  */
00487 void
00488 nmg_vls_struct_counts(struct bu_vls *str, const struct nmg_struct_counts *ctr)
00489 {
00490         BU_CK_VLS( str );
00491 
00492         bu_vls_printf(str, " Actual structure counts:\n");
00493         bu_vls_printf(str, "\t%6ld model\n", ctr->model);
00494         bu_vls_printf(str, "\t%6ld region\n", ctr->region);
00495         bu_vls_printf(str, "\t%6ld region_a\n", ctr->region_a);
00496         bu_vls_printf(str, "\t%6ld shell\n", ctr->shell);
00497         bu_vls_printf(str, "\t%6ld shell_a\n", ctr->shell_a);
00498         bu_vls_printf(str, "\t%6ld face\n", ctr->face);
00499         bu_vls_printf(str, "\t%6ld face_g_plane\n", ctr->face_g_plane);
00500         bu_vls_printf(str, "\t%6ld face_g_snurb\n", ctr->face_g_snurb);
00501         bu_vls_printf(str, "\t%6ld faceuse\n", ctr->faceuse);
00502         bu_vls_printf(str, "\t%6ld loopuse\n", ctr->loopuse);
00503         bu_vls_printf(str, "\t%6ld loop\n", ctr->loop);
00504         bu_vls_printf(str, "\t%6ld loop_g\n", ctr->loop_g);
00505         bu_vls_printf(str, "\t%6ld edgeuse\n", ctr->edgeuse);
00506         bu_vls_printf(str, "\t%6ld edge\n", ctr->edge);
00507         bu_vls_printf(str, "\t%6ld edge_g_lseg\n", ctr->edge_g_lseg);
00508         bu_vls_printf(str, "\t%6ld edge_g_cnurb\n", ctr->edge_g_cnurb);
00509         bu_vls_printf(str, "\t%6ld vertexuse\n", ctr->vertexuse);
00510         bu_vls_printf(str, "\t%6ld vertexuse_a_plane\n", ctr->vertexuse_a_plane);
00511         bu_vls_printf(str, "\t%6ld vertexuse_a_cnurb\n", ctr->vertexuse_a_cnurb);
00512         bu_vls_printf(str, "\t%6ld vertex\n", ctr->vertex);
00513         bu_vls_printf(str, "\t%6ld vertex_g\n", ctr->vertex_g);
00514         bu_vls_printf(str, " Abstractions:\n");
00515         bu_vls_printf(str, "\t%6ld max_structs\n", ctr->max_structs);
00516         bu_vls_printf(str, "\t%6ld face_loops\n", ctr->face_loops);
00517         bu_vls_printf(str, "\t%6ld face_edges\n", ctr->face_edges);
00518         bu_vls_printf(str, "\t%6ld face_lone_verts\n", ctr->face_lone_verts);
00519         bu_vls_printf(str, "\t%6ld wire_loops\n", ctr->wire_loops);
00520         bu_vls_printf(str, "\t%6ld wire_loop_edges\n", ctr->wire_loop_edges);
00521         bu_vls_printf(str, "\t%6ld wire_edges\n", ctr->wire_edges);
00522         bu_vls_printf(str, "\t%6ld wire_lone_verts\n", ctr->wire_lone_verts);
00523         bu_vls_printf(str, "\t%6ld shells_of_lone_vert\n", ctr->shells_of_lone_vert);
00524 }
00525 
00526 /**
00527  *                      N M G _ P R _ S T R U C T _ C O U N T S
00528  */
00529 void
00530 nmg_pr_struct_counts(const struct nmg_struct_counts *ctr, const char *str)
00531 {
00532         struct bu_vls           vls;
00533 
00534         bu_log("nmg_pr_count(%s)\n", str);
00535 
00536         bu_vls_init( &vls );
00537         nmg_vls_struct_counts( &vls, ctr );
00538         bu_log("%s", bu_vls_addr( &vls ) );
00539         bu_vls_free( &vls );
00540 }
00541 
00542 /**
00543  *                      N M G _ M _ S T R U C T _ C O U N T
00544  *
00545  *  Returns -
00546  *      Pointer to magic-number/structure-base pointer array,
00547  *      indexed by nmg structure index.
00548  *      Caller is responsible for freeing it.
00549  */
00550 long **
00551 nmg_m_struct_count(register struct nmg_struct_counts *ctr, const struct model *m)
00552 {
00553         struct nmgregion        *r;
00554         struct shell            *s;
00555         struct faceuse          *fu;
00556         struct face             *f;
00557         struct loopuse          *lu;
00558         struct loop             *l;
00559         struct edgeuse          *eu;
00560         struct edge             *e;
00561         struct vertexuse        *vu;
00562         struct vertex           *v;
00563         register long           **ptrs;
00564 
00565 #define NMG_UNIQ_INDEX(_p,_type)        \
00566         if( (_p)->index > m->maxindex )  { \
00567                 bu_log("x%x (%s) has index %d, m->maxindex=%d\n", (_p), \
00568                         bu_identify_magic(*((long *)(_p))), (_p)->index, m->maxindex ); \
00569                 rt_bomb("nmg_m_struct_count index overflow\n"); \
00570         } \
00571         if( ptrs[(_p)->index] == (long *)0 )  { \
00572                 ptrs[(_p)->index] = (long *)(_p); \
00573                 ctr->_type++; \
00574         }
00575 
00576 #define UNIQ_VU(_vu)    { \
00577                 NMG_CK_VERTEXUSE(_vu); \
00578                 NMG_UNIQ_INDEX(_vu, vertexuse); \
00579                 if(_vu->a.magic_p) switch(*_vu->a.magic_p) { \
00580                 case NMG_VERTEXUSE_A_PLANE_MAGIC: \
00581                         NMG_UNIQ_INDEX(_vu->a.plane_p, vertexuse_a_plane); \
00582                         break; \
00583                 case NMG_VERTEXUSE_A_CNURB_MAGIC: \
00584                         NMG_UNIQ_INDEX(_vu->a.cnurb_p, vertexuse_a_cnurb); \
00585                         break; \
00586                 } \
00587                 v = _vu->v_p; \
00588                 NMG_CK_VERTEX(v); \
00589                 NMG_UNIQ_INDEX(v, vertex); \
00590                 if(v->vg_p)  { \
00591                         NMG_CK_VERTEX_G(v->vg_p); \
00592                         NMG_UNIQ_INDEX(v->vg_p, vertex_g); \
00593                 } \
00594         }
00595 
00596         NMG_CK_MODEL(m);
00597         bzero( (char *)ctr, sizeof(*ctr) );
00598 
00599         ptrs = (long **)bu_calloc( m->maxindex+1, sizeof(long *), "nmg_m_count ptrs[]" );
00600 
00601         NMG_UNIQ_INDEX(m, model);
00602         ctr->max_structs = m->maxindex;
00603         for( BU_LIST_FOR( r, nmgregion, &m->r_hd ) )  {
00604                 NMG_CK_REGION(r);
00605                 NMG_UNIQ_INDEX(r, region);
00606                 if(r->ra_p)  {
00607                         NMG_CK_REGION_A(r->ra_p);
00608                         NMG_UNIQ_INDEX(r->ra_p, region_a);
00609                 }
00610                 for( BU_LIST_FOR( s, shell, &r->s_hd ) )  {
00611                         NMG_CK_SHELL(s);
00612                         NMG_UNIQ_INDEX(s, shell);
00613                         if(s->sa_p)  {
00614                                 NMG_CK_SHELL_A(s->sa_p);
00615                                 NMG_UNIQ_INDEX(s->sa_p, shell_a);
00616                         }
00617                         /* Faces in shell */
00618                         for( BU_LIST_FOR( fu, faceuse, &s->fu_hd ) )  {
00619                                 NMG_CK_FACEUSE(fu);
00620                                 NMG_UNIQ_INDEX(fu, faceuse);
00621                                 f = fu->f_p;
00622                                 NMG_CK_FACE(f);
00623                                 NMG_UNIQ_INDEX(f, face);
00624                                 if( f->g.magic_p )  switch( *f->g.magic_p )  {
00625                                 case NMG_FACE_G_PLANE_MAGIC:
00626                                         NMG_UNIQ_INDEX(f->g.plane_p, face_g_plane);
00627                                         break;
00628                                 case NMG_FACE_G_SNURB_MAGIC:
00629                                         NMG_UNIQ_INDEX(f->g.snurb_p, face_g_snurb);
00630                                         break;
00631                                 }
00632                                 /* Loops in face */
00633                                 for( BU_LIST_FOR( lu, loopuse, &fu->lu_hd ) )  {
00634                                         NMG_CK_LOOPUSE(lu);
00635                                         NMG_UNIQ_INDEX(lu, loopuse);
00636                                         l = lu->l_p;
00637                                         NMG_CK_LOOP(l);
00638                                         NMG_UNIQ_INDEX(l, loop);
00639                                         if( l->lg_p )  {
00640                                                 NMG_CK_LOOP_G(l->lg_p);
00641                                                 NMG_UNIQ_INDEX(l->lg_p, loop_g);
00642                                         }
00643                                         if( BU_LIST_FIRST_MAGIC(&lu->down_hd) == NMG_VERTEXUSE_MAGIC )  {
00644                                                 /* Loop of Lone vertex */
00645                                                 ctr->face_lone_verts++;
00646                                                 vu = BU_LIST_FIRST(vertexuse, &lu->down_hd);
00647                                                 UNIQ_VU(vu);
00648                                                 continue;
00649                                         }
00650                                         ctr->face_loops++;
00651                                         for( BU_LIST_FOR( eu, edgeuse, &lu->down_hd ) )  {
00652                                                 ctr->face_edges++;
00653                                                 NMG_CK_EDGEUSE(eu);
00654                                                 NMG_UNIQ_INDEX(eu, edgeuse);
00655                                                 e = eu->e_p;
00656                                                 NMG_CK_EDGE(e);
00657                                                 NMG_UNIQ_INDEX(e, edge);
00658                                                 if( eu->g.magic_p )  switch( *eu->g.magic_p )  {
00659                                                 case NMG_EDGE_G_LSEG_MAGIC:
00660                                                         NMG_UNIQ_INDEX(eu->g.lseg_p, edge_g_lseg);
00661                                                         break;
00662                                                 case NMG_EDGE_G_CNURB_MAGIC:
00663                                                         NMG_UNIQ_INDEX(eu->g.cnurb_p, edge_g_cnurb);
00664                                                         break;
00665                                                 }
00666                                                 vu = eu->vu_p;
00667                                                 UNIQ_VU(vu);
00668                                         }
00669                                 }
00670                         }
00671                         /* Wire loops in shell */
00672                         for( BU_LIST_FOR( lu, loopuse, &s->lu_hd ) )  {
00673                                 NMG_CK_LOOPUSE(lu);
00674                                 NMG_UNIQ_INDEX(lu, loopuse);
00675                                 l = lu->l_p;
00676                                 NMG_CK_LOOP(l);
00677                                 NMG_UNIQ_INDEX(l, loop);
00678                                 if( l->lg_p )  {
00679                                         NMG_CK_LOOP_G(l->lg_p);
00680                                         NMG_UNIQ_INDEX(l->lg_p, loop_g);
00681                                 }
00682                                 if( BU_LIST_FIRST_MAGIC(&lu->down_hd) == NMG_VERTEXUSE_MAGIC )  {
00683                                         ctr->wire_lone_verts++;
00684                                         /* Wire loop of Lone vertex */
00685                                         vu = BU_LIST_FIRST( vertexuse, &lu->down_hd );
00686                                         UNIQ_VU(vu);
00687                                         continue;
00688                                 }
00689                                 ctr->wire_loops++;
00690                                 for( BU_LIST_FOR( eu, edgeuse, &lu->down_hd ) )  {
00691                                         NMG_CK_EDGEUSE(eu);
00692                                         NMG_UNIQ_INDEX(eu, edgeuse);
00693                                         e = eu->e_p;
00694                                         NMG_CK_EDGE(e);
00695                                         NMG_UNIQ_INDEX(e, edge);
00696                                         if( eu->g.magic_p )  switch( *eu->g.magic_p )  {
00697                                         case NMG_EDGE_G_LSEG_MAGIC:
00698                                                 NMG_UNIQ_INDEX(eu->g.lseg_p, edge_g_lseg);
00699                                                 break;
00700                                         case NMG_EDGE_G_CNURB_MAGIC:
00701                                                 NMG_UNIQ_INDEX(eu->g.cnurb_p, edge_g_cnurb);
00702                                                 break;
00703                                         }
00704                                         vu = eu->vu_p;
00705                                         UNIQ_VU(vu);
00706                                         ctr->wire_loop_edges++;
00707                                 }
00708                         }
00709                         /* Wire edges in shell */
00710                         for( BU_LIST_FOR( eu, edgeuse, &s->eu_hd ) )  {
00711                                 NMG_CK_EDGEUSE(eu);
00712                                 ctr->wire_edges++;
00713                                 NMG_UNIQ_INDEX(eu, edgeuse);
00714                                 e = eu->e_p;
00715                                 NMG_CK_EDGE(e);
00716                                 NMG_UNIQ_INDEX(e, edge);
00717                                 if( eu->g.magic_p )  switch( *eu->g.magic_p )  {
00718                                 case NMG_EDGE_G_LSEG_MAGIC:
00719                                         NMG_UNIQ_INDEX(eu->g.lseg_p, edge_g_lseg);
00720                                         break;
00721                                 case NMG_EDGE_G_CNURB_MAGIC:
00722                                         NMG_UNIQ_INDEX(eu->g.cnurb_p, edge_g_cnurb);
00723                                         break;
00724                                 }
00725                                 vu = eu->vu_p;
00726                                 UNIQ_VU(vu);
00727                         }
00728                         /* Lone vertex in shell */
00729                         if( (vu = s->vu_p) )  {
00730                                 ctr->shells_of_lone_vert++;
00731                                 UNIQ_VU(vu);
00732                         }
00733                 }
00734         }
00735         /* Caller must free them */
00736         return ptrs;
00737 #undef UNIQ_VU
00738 }
00739 
00740 /**
00741  *
00742  *  Count 'em up, and print 'em out.
00743  */
00744 void
00745 nmg_struct_counts(const struct model *m, const char *str)
00746 {
00747         struct nmg_struct_counts        cnts;
00748         long    **tab;
00749 
00750         NMG_CK_MODEL(m);
00751 
00752         tab = nmg_m_struct_count( &cnts, m );
00753         bu_free( (char *)tab, "nmg_m_struct_count" );
00754         nmg_pr_struct_counts( &cnts, str );
00755 }
00756 
00757 /**                     N M G _ M E R G _ M O D E L S
00758  *
00759  *      Combine two NMG model trees into one single NMG model.  The
00760  *      first model inherits the nmgregions of the second.  The second
00761  *      model pointer is freed before return.
00762  */
00763 void
00764 nmg_merge_models(struct model *m1, struct model *m2)
00765 {
00766         struct nmgregion *r;
00767 
00768         NMG_CK_MODEL(m1);
00769         NMG_CK_MODEL(m2);
00770 
00771         /* first reorder the first model to "compress" the
00772          * number space if possible.
00773          */
00774         nmg_m_reindex(m1, 0);
00775 
00776         if( m1 == m2 ) /* nothing to do */
00777                 return;
00778 
00779         /* now re-order the second model starting with an index number
00780          * of m1->maxindex.
00781          *
00782          * We might get away with using m1->maxindex-1, since the first
00783          * value is assigned to the second model structure, and we will
00784          * shortly be freeing the second model struct.
00785          */
00786 
00787         nmg_m_reindex(m2, m1->maxindex);
00788         m1->maxindex = m2->maxindex;            /* big enough for both */
00789 
00790         /* Rehome all the regions in m2, and move them from m2 to m1 */
00791         for ( BU_LIST_FOR(r, nmgregion, &(m2->r_hd)) ) {
00792                 NMG_CK_REGION(r);
00793                 r->m_p = m1;
00794         }
00795         BU_LIST_APPEND_LIST(&(m1->r_hd), &(m2->r_hd));
00796 
00797         FREE_MODEL(m2);
00798 }
00799 
00800 #define CHECK_INDEX( _p ) if((_p)->index > maxindex ) maxindex = (_p)->index
00801 #define CHECK_VU_INDEX( _vu) {\
00802                 NMG_CK_VERTEXUSE(_vu); \
00803                 CHECK_INDEX(_vu); \
00804                 if(_vu->a.magic_p)  switch(*_vu->a.magic_p)  { \
00805                 case NMG_VERTEXUSE_A_PLANE_MAGIC: \
00806                         CHECK_INDEX(_vu->a.plane_p); \
00807                         break; \
00808                 case NMG_VERTEXUSE_A_CNURB_MAGIC: \
00809                         CHECK_INDEX(_vu->a.cnurb_p); \
00810                         break; \
00811                 } \
00812                 v = _vu->v_p; \
00813                 NMG_CK_VERTEX(v); \
00814                 CHECK_INDEX(v); \
00815                 if(v->vg_p) CHECK_INDEX(v->vg_p); \
00816         }
00817 
00818 /**
00819  *                      N M G _ F I N D _ M A X _ I N D E X
00820  */
00821 long
00822 nmg_find_max_index(const struct model *m)
00823 {
00824         long                    maxindex=0;
00825         struct nmgregion        *r;
00826         struct shell            *s;
00827         struct faceuse          *fu;
00828         struct face             *f;
00829         struct loopuse          *lu;
00830         struct loop             *l;
00831         register struct edgeuse         *eu;
00832         struct edge                     *e;
00833         register struct vertexuse       *vu;
00834         struct vertex                   *v;
00835 
00836         for( BU_LIST_FOR( r, nmgregion, &m->r_hd ) )  {
00837                 NMG_CK_REGION(r);
00838                 CHECK_INDEX(r);
00839                 if( r->ra_p )  CHECK_INDEX(r->ra_p);
00840                 for( BU_LIST_FOR( s, shell, &r->s_hd ) )  {
00841                         NMG_CK_SHELL(s);
00842                         CHECK_INDEX(s);
00843                         if( s->sa_p )  CHECK_INDEX(s->sa_p);
00844                         /* Faces in shell */
00845                         for( BU_LIST_FOR( fu, faceuse, &s->fu_hd ) )  {
00846                                 NMG_CK_FACEUSE(fu);
00847                                 CHECK_INDEX(fu);
00848                                 f = fu->f_p;
00849                                 NMG_CK_FACE(f);
00850                                 CHECK_INDEX(f);
00851                                 if( f->g.plane_p ) switch( *f->g.magic_p )  {
00852                                 case NMG_FACE_G_PLANE_MAGIC:
00853                                         CHECK_INDEX(f->g.plane_p);
00854                                         break;
00855                                 case NMG_FACE_G_SNURB_MAGIC:
00856                                         CHECK_INDEX(f->g.snurb_p);
00857                                         break;
00858                                 }
00859                                 /* Loops in face */
00860                                 for( BU_LIST_FOR( lu, loopuse, &fu->lu_hd ) )  {
00861                                         NMG_CK_LOOPUSE(lu);
00862                                         CHECK_INDEX(lu);
00863                                         l = lu->l_p;
00864                                         NMG_CK_LOOP(l);
00865                                         CHECK_INDEX(l);
00866                                         if( l->lg_p )  CHECK_INDEX(l->lg_p);
00867                                         if( BU_LIST_FIRST_MAGIC(&lu->down_hd) == NMG_VERTEXUSE_MAGIC )  {
00868                                                 /* Loop of Lone vertex */
00869                                                 vu = BU_LIST_FIRST( vertexuse, &lu->down_hd );
00870                                                 CHECK_VU_INDEX(vu);
00871                                                 continue;
00872                                         }
00873                                         for( BU_LIST_FOR( eu, edgeuse, &lu->down_hd ) )  {
00874                                                 NMG_CK_EDGEUSE(eu);
00875                                                 CHECK_INDEX(eu);
00876                                                 e = eu->e_p;
00877                                                 NMG_CK_EDGE(e);
00878                                                 CHECK_INDEX(e);
00879                                                 if( eu->g.magic_p ) switch(*eu->g.magic_p)  {
00880                                                 case NMG_EDGE_G_LSEG_MAGIC:
00881                                                         CHECK_INDEX(eu->g.lseg_p);
00882                                                         break;
00883                                                 case NMG_EDGE_G_CNURB_MAGIC:
00884                                                         CHECK_INDEX(eu->g.cnurb_p);
00885                                                         break;
00886                                                 }
00887                                                 vu = eu->vu_p;
00888                                                 CHECK_VU_INDEX(vu);
00889                                         }
00890                                 }
00891                         }
00892                         /* Wire loops in shell */
00893                         for( BU_LIST_FOR( lu, loopuse, &s->lu_hd ) )  {
00894                                 NMG_CK_LOOPUSE(lu);
00895                                 CHECK_INDEX(lu);
00896                                 l = lu->l_p;
00897                                 NMG_CK_LOOP(l);
00898                                 CHECK_INDEX(l);
00899                                 if( l->lg_p )  CHECK_INDEX(l->lg_p);
00900                                 if( BU_LIST_FIRST_MAGIC(&lu->down_hd) == NMG_VERTEXUSE_MAGIC )  {
00901                                         /* Wire loop of Lone vertex */
00902                                         vu = BU_LIST_FIRST( vertexuse, &lu->down_hd );
00903                                         CHECK_VU_INDEX(vu);
00904                                         continue;
00905                                 }
00906                                 for( BU_LIST_FOR( eu, edgeuse, &lu->down_hd ) )  {
00907                                         NMG_CK_EDGEUSE(eu);
00908                                         CHECK_INDEX(eu);
00909                                         e = eu->e_p;
00910                                         NMG_CK_EDGE(e);
00911                                         CHECK_INDEX(e);
00912                                         if( eu->g.magic_p ) switch(*eu->g.magic_p)  {
00913                                         case NMG_EDGE_G_LSEG_MAGIC:
00914                                                 CHECK_INDEX(eu->g.lseg_p);
00915                                                 break;
00916                                         case NMG_EDGE_G_CNURB_MAGIC:
00917                                                 CHECK_INDEX(eu->g.cnurb_p);
00918                                                 break;
00919                                         }
00920                                         vu = eu->vu_p;
00921                                         CHECK_VU_INDEX(vu);
00922                                 }
00923                         }
00924                         /* Wire edges in shell */
00925                         for( BU_LIST_FOR( eu, edgeuse, &s->eu_hd ) )  {
00926                                 NMG_CK_EDGEUSE(eu);
00927                                 CHECK_INDEX(eu);
00928                                 e = eu->e_p;
00929                                 NMG_CK_EDGE(e);
00930                                 CHECK_INDEX(e);
00931                                 if( eu->g.magic_p ) switch(*eu->g.magic_p)  {
00932                                 case NMG_EDGE_G_LSEG_MAGIC:
00933                                         CHECK_INDEX(eu->g.lseg_p);
00934                                         break;
00935                                 case NMG_EDGE_G_CNURB_MAGIC:
00936                                         CHECK_INDEX(eu->g.cnurb_p);
00937                                         break;
00938                                 }
00939                                 vu = eu->vu_p;
00940                                 CHECK_VU_INDEX(vu);
00941                         }
00942                         /* Lone vertex in shell */
00943                         if( (vu = s->vu_p) )  {
00944                                 CHECK_VU_INDEX(vu);
00945                         }
00946                 }
00947         }
00948         return( maxindex );
00949 }
00950 
00951 /*
00952  * Local Variables:
00953  * mode: C
00954  * tab-width: 8
00955  * c-basic-offset: 4
00956  * indent-tabs-mode: t
00957  * End:
00958  * ex: shiftwidth=4 tabstop=8
00959  */

Generated on Mon Sep 18 01:24:53 2006 for BRL-CAD by  doxygen 1.4.6