nmg_ck.c

Go to the documentation of this file.
00001 /*                        N M G _ C K . C
00002  * BRL-CAD
00003  *
00004  * Copyright (c) 1993-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_ck.c
00026  *  Validators and consistency checkers for NMG data structures.
00027  *
00028  *  Authors -
00029  *      Lee A. Butler
00030  *      Michael John Muuss
00031  *      John R. Anderson
00032  *
00033  *  Source -
00034  *      The U. S. Army Research Laboratory
00035  *      Aberdeen Proving Ground, Maryland  21005-5068  USA
00036  */
00037 /*@}*/
00038 #ifndef lint
00039 static const char RCSid[] = "@(#)$Header: /cvsroot/brlcad/brlcad/src/librt/nmg_ck.c,v 14.14 2006/09/16 02:04:25 lbutler Exp $ (ARL)";
00040 #endif
00041 
00042 #include "common.h"
00043 
00044 #include <stddef.h>
00045 #include <stdio.h>
00046 #ifdef HAVE_STRING_H
00047 #  include <string.h>
00048 #else
00049 #  include <strings.h>
00050 #endif
00051 
00052 #include "machine.h"
00053 #include "vmath.h"
00054 #include "nmg.h"
00055 #include "raytrace.h"
00056 
00057 
00058 /************************************************************************
00059  *                                                                      *
00060  *                      Validator Routines                              *
00061  *                                                                      *
00062  ************************************************************************/
00063 
00064 /**
00065  *                      N M G _ V V G
00066  *
00067  *  Verify vertex geometry
00068  */
00069 void
00070 nmg_vvg(const struct vertex_g *vg)
00071 {
00072         NMG_CK_VERTEX_G(vg);
00073 }
00074 
00075 /**
00076  *                      N M G _ V V E R T E X
00077  *
00078  *  Verify a vertex
00079  */
00080 void
00081 nmg_vvertex(const struct vertex *v, const struct vertexuse *vup)
00082 {
00083         struct vertexuse *vu;
00084         int vup_is_in_list = 0;
00085 
00086         NMG_CK_VERTEX(v);
00087 
00088         for( BU_LIST_FOR( vu, vertexuse, &v->vu_hd ) )  {
00089                 NMG_CK_VERTEXUSE(vu);
00090                 if (vu->v_p != v)
00091                         rt_bomb("nmg_vvertex() a vertexuse in my list doesn't share my vertex\n");
00092                 if (vu == vup)
00093                         vup_is_in_list = 1;
00094         }
00095         if (v->vg_p) nmg_vvg(v->vg_p);
00096         if ( ! vup_is_in_list )
00097                 rt_bomb("nmg_vvertex() vup not found in list of vertexuses\n");
00098 }
00099 
00100 /* Verify vertex attributes */
00101 void
00102 nmg_vvua(const long int *vua)
00103 {
00104         NMG_CK_VERTEXUSE_A_EITHER(vua);
00105 }
00106 
00107 /**
00108  *                      N M G _ V V U
00109  *
00110  *  Verify vertexuse
00111  */
00112 void
00113 nmg_vvu(const struct vertexuse *vu, const long int *up_magic_p)
00114 {
00115         long    magic;
00116 
00117         NMG_CK_VERTEXUSE(vu);
00118         if (vu->up.magic_p != up_magic_p)  {
00119                 bu_log("nmg_vvu() up is %s, s/b %s\n",
00120                         bu_identify_magic( *vu->up.magic_p ),
00121                         bu_identify_magic( *up_magic_p ) );
00122                 rt_bomb("nmg_vvu() vertexuse denies parent\n");
00123         }
00124 
00125         if (!vu->l.forw)
00126                 rt_bomb("nmg_vvu() vertexuse has null forw pointer\n");
00127 
00128         magic = BU_LIST_FIRST_MAGIC( &vu->l );
00129         if( magic != NMG_VERTEXUSE_MAGIC && magic != BU_LIST_HEAD_MAGIC )
00130                 rt_bomb("nmg_vvu() vertexuse forw is bad vertexuse\n");
00131 
00132         if (BU_LIST_PNEXT_PLAST(vertexuse,vu) != vu )
00133                 rt_bomb("nmg_vvu() vertexuse not back of next vertexuse\n");
00134 
00135         nmg_vvertex(vu->v_p, vu);
00136 
00137         if (vu->a.magic_p) nmg_vvua(vu->a.magic_p);
00138 }
00139 
00140 /* Verify edge geometry */
00141 void
00142 nmg_veg(const long int *eg)
00143 {
00144         struct bu_list  *eu2;
00145 
00146         NMG_CK_EDGE_G_EITHER(eg);
00147         switch( *eg )  {
00148         case NMG_EDGE_G_LSEG_MAGIC:
00149                 bu_ck_list_magic( &((struct edge_g_lseg *)eg)->eu_hd2,
00150                         "nmg_veg() edge_g_lseg eu_hd2 list",
00151                         NMG_EDGEUSE2_MAGIC );
00152                 break;
00153         case NMG_EDGE_G_CNURB_MAGIC:
00154                 bu_ck_list_magic( &((struct edge_g_cnurb *)eg)->eu_hd2,
00155                         "nmg_veg() edge_g_cnurb eu_hd2 list",
00156                         NMG_EDGEUSE2_MAGIC );
00157                 break;
00158         }
00159 
00160         /* Ensure that all edgeuses on the edge_g_* list point to me */
00161         for( BU_LIST_FOR( eu2, bu_list, &((struct edge_g_lseg *)eg)->eu_hd2 ) )  {
00162                 struct edgeuse  *eu;
00163 
00164                 if( eu2 == NULL)
00165                 {
00166                          rt_bomb("nmg_veg null eu2\n");
00167                 }
00168                 eu = BU_LIST_MAIN_PTR( edgeuse, eu2, l2 );
00169                 NMG_CK_EDGEUSE(eu);
00170                 if( eu->g.magic_p == eg )  continue;
00171                 bu_log("eg=x%x, eu=x%x, eu->g=x%x\n", eg, eu, eu->g.magic_p);
00172                 bu_log("nmg_veg() edgeuse is on wrong eu_hd2 list for eu->g\n");
00173         }
00174 }
00175 
00176 /**
00177  *                      N M G _ V E D G E
00178  *
00179  *  Verify edge
00180  */
00181 void
00182 nmg_vedge(const struct edge *e, const struct edgeuse *eup)
00183 {
00184         const struct edgeuse *eu;
00185         int is_use = 0;         /* flag: eup is in edge's use list */
00186 
00187         NMG_CK_EDGE(e);
00188         NMG_CK_EDGEUSE(eup);
00189         NMG_CK_VERTEXUSE(eup->vu_p);
00190         NMG_CK_VERTEX(eup->vu_p->v_p);
00191         NMG_CK_EDGEUSE(eup->eumate_p);
00192         NMG_CK_VERTEXUSE(eup->eumate_p->vu_p);
00193         NMG_CK_VERTEX(eup->eumate_p->vu_p->v_p);
00194 
00195         if (!e->eu_p) rt_bomb("nmg_vedge() edge has null edgeuse pointer\n");
00196 
00197         NMG_CK_EDGEUSE( e->eu_p );
00198 
00199         eu = eup;
00200         do {
00201                 NMG_CK_EDGEUSE(eu);
00202                 NMG_CK_EDGEUSE(eu->eumate_p);
00203                 if (eu == eup || eu->eumate_p == eup)
00204                         is_use = 1;
00205 
00206                 NMG_CK_VERTEXUSE(eu->vu_p);
00207                 NMG_CK_VERTEX(eu->vu_p->v_p);
00208                 if (eu->vu_p->v_p == eup->vu_p->v_p) {
00209                         if (eu->eumate_p->vu_p->v_p != eup->eumate_p->vu_p->v_p)
00210                         {
00211                                 bu_log("nmg_vedge() edgeuse mate does not have correct vertex\n");
00212                                 bu_log( "(eu=x%x, eu->vu_p->v_p=x%x, eu->eumate_p->vu_p->v_p=x%x)\n",
00213                                         eu, eu->vu_p->v_p, eu->eumate_p->vu_p->v_p);
00214                                 bu_log( "(eup=x%x, eup->vu_p->v_p=x%x, eup->eumate_p->vu_p->v_p=x%x)\n",
00215                                         eup, eup->vu_p->v_p, eup->eumate_p->vu_p->v_p);
00216                                 rt_bomb("nmg_vedge() edgeuse mate does not have correct vertex\n");
00217                         }
00218                 } else if (eu->vu_p->v_p == eup->eumate_p->vu_p->v_p) {
00219                         if (eu->eumate_p->vu_p->v_p != eup->vu_p->v_p)
00220                         {
00221                                 bu_log("nmg_vedge() edgeuse does not have correct vertex\n" );
00222                                 bu_log( "(eu=x%x, eu->vu_p->v_p=x%x, eu->eumate_p->vu_p->v_p=x%x)\n",
00223                                         eu, eu->vu_p->v_p, eu->eumate_p->vu_p->v_p);
00224                                 bu_log( "(eup=x%x, eup->vu_p->v_p=x%x, eup->eumate_p->vu_p->v_p=x%x)\n",
00225                                         eup, eup->vu_p->v_p, eup->eumate_p->vu_p->v_p);
00226                                 rt_bomb("nmg_vedge() edgeuse does not have correct vertex\n");
00227                         }
00228                 } else
00229                 {
00230                         bu_log("nmg_vedge() edgeuse does not share vertex endpoint\n" );
00231                         bu_log( "(eu=x%x, eu->vu_p->v_p=x%x, eu->eumate_p->vu_p->v_p=x%x)\n",
00232                                 eu, eu->vu_p->v_p, eu->eumate_p->vu_p->v_p);
00233                         bu_log( "(eup=x%x, eup->vu_p->v_p=x%x, eup->eumate_p->vu_p->v_p=x%x)\n",
00234                                 eup, eup->vu_p->v_p, eup->eumate_p->vu_p->v_p);
00235                         rt_bomb("nmg_vedge() edgeuse does not share vertex endpoint\n");
00236                 }
00237 
00238                 eu = eu->eumate_p->radial_p;
00239         } while (eu != eup);
00240 
00241         if (!is_use)
00242                 rt_bomb("nmg_vedge() Cannot get from edge to parent edgeuse\n");
00243 }
00244 
00245 /**
00246  *                      N M G _ V E U
00247  *
00248  *  Verify edgeuse list.
00249  */
00250 void
00251 nmg_veu(const struct bu_list *hp, const long int *up_magic_p)
00252 {
00253         struct edgeuse  *eu;
00254         struct edgeuse  *eunext;
00255         struct edgeuse  *eulast;
00256         long            up_magic;
00257 
00258         bu_ck_list_magic( hp, "nmg_veu() edegeuse list head", NMG_EDGEUSE_MAGIC );
00259 
00260         up_magic = *up_magic_p;
00261         switch( up_magic )  {
00262         case NMG_SHELL_MAGIC:
00263         case NMG_LOOPUSE_MAGIC:
00264                 break;
00265         default:
00266                 rt_bomb("nmg_veu() bad up_magic_p\n");
00267         }
00268         for( BU_LIST_FOR( eu, edgeuse, hp ) )  {
00269                 NMG_CK_EDGEUSE(eu);
00270 
00271                 if (eu->up.magic_p != up_magic_p)
00272                         rt_bomb("nmg_veu() edgeuse denies parentage\n");
00273 
00274                 if (!eu->l.forw)
00275                         rt_bomb("nmg_veu() edgeuse has Null \"forw\" pointer\n");
00276                 eunext = BU_LIST_PNEXT_CIRC( edgeuse, eu );
00277                 eulast = BU_LIST_PPREV_CIRC(edgeuse, &eu->l);
00278                 if (eunext->l.magic != NMG_EDGEUSE_MAGIC)
00279                         rt_bomb("nmg_veu() edgeuse forw is bad edgeuse\n");
00280                 if (eulast->l.magic != NMG_EDGEUSE_MAGIC)
00281                         rt_bomb("nmg_veu() edgeuse back is bad edgeuse\n");
00282                 NMG_CK_EDGEUSE(eunext);
00283                 NMG_CK_EDGEUSE(eulast);
00284 
00285                 /* Check that forw->back is us */
00286                 if (BU_LIST_PPREV_CIRC(edgeuse,eunext) != eu )  {
00287                     if (eunext->l.back)
00288                         rt_bomb("nmg_veu() next edgeuse has back that points elsewhere\n");
00289                     rt_bomb("nmg_veu() next edgeuse has NULL back\n");
00290                 }
00291 
00292                 /*
00293                  *  For edgeuses in loops, ensure that vertices are shared.
00294                  *  This does not apply to wire edgeuses in the shell.
00295                  */
00296                 if ( up_magic == NMG_LOOPUSE_MAGIC &&
00297                      eu->vu_p->v_p != eulast->eumate_p->vu_p->v_p) {
00298                         bu_log("eu=x%x, e=x%x\n", eu, eu->e_p );
00299                         bu_log("eulast=x%x, e=x%x\n", eulast, eulast->e_p);
00300                         bu_log("            eu: (%g, %g, %g) <--> (%g, %g, %g)\n",
00301                                 V3ARGS(eu->vu_p->v_p->vg_p->coord),
00302                                 V3ARGS(eu->eumate_p->vu_p->v_p->vg_p->coord) );
00303                         bu_log("        eulast: (%g, %g, %g) <--> (%g, %g, %g)\n",
00304                                 V3ARGS(eulast->vu_p->v_p->vg_p->coord),
00305                                 V3ARGS(eulast->eumate_p->vu_p->v_p->vg_p->coord) );
00306                         bu_log("unshared vertex (mine) v=x%x: (%g, %g, %g)\n",
00307                                 eu->vu_p->v_p,
00308                                 V3ARGS(eu->vu_p->v_p->vg_p->coord) );
00309                         bu_log("\t\t (last->eumate_p) v=x%x: (%g, %g, %g)\n",
00310                                 eulast->eumate_p->vu_p->v_p,
00311                                 V3ARGS(eulast->eumate_p->vu_p->v_p->vg_p->coord) );
00312                         nmg_pr_lu_briefly(eu->up.lu_p, (char *)NULL);
00313                         nmg_pr_lu_briefly(eu->up.lu_p->lumate_p, (char *)NULL);
00314                         rt_bomb("nmg_veu() discontinuous edgeloop mine/last\n");
00315                 }
00316                 if ( up_magic == NMG_LOOPUSE_MAGIC &&
00317                      eunext->vu_p->v_p != eu->eumate_p->vu_p->v_p) {
00318                         bu_log("eu=x%x, e=x%x\n", eu, eu->e_p );
00319                         bu_log("eunext=x%x, e=x%x\n", eunext, eunext->e_p);
00320                         bu_log("            eu: (%g, %g, %g) <--> (%g, %g, %g)\n",
00321                                 V3ARGS(eu->vu_p->v_p->vg_p->coord),
00322                                 V3ARGS(eu->eumate_p->vu_p->v_p->vg_p->coord) );
00323                         bu_log("        eunext: (%g, %g, %g) <--> (%g, %g, %g)\n",
00324                                 V3ARGS(eunext->vu_p->v_p->vg_p->coord),
00325                                 V3ARGS(eunext->eumate_p->vu_p->v_p->vg_p->coord) );
00326                         bu_log("unshared vertex (mate) v=x%x: (%g, %g, %g)\n",
00327                                 eu->eumate_p->vu_p->v_p,
00328                                 V3ARGS(eu->eumate_p->vu_p->v_p->vg_p->coord) );
00329                         bu_log("\t\t (next) v=x%x: (%g, %g, %g)\n",
00330                                 eunext->vu_p->v_p,
00331                                 V3ARGS(eunext->vu_p->v_p->vg_p->coord) );
00332                         nmg_pr_lu_briefly(eu->up.lu_p, (char *)NULL);
00333                         nmg_pr_lu_briefly(eu->up.lu_p->lumate_p, (char *)NULL);
00334                         rt_bomb("nmg_veu() discontinuous edgeloop next/mate\n");
00335                 }
00336 
00337                 /* Check mate and radial */
00338                 if (eu->eumate_p->l.magic != NMG_EDGEUSE_MAGIC)
00339                         rt_bomb("nmg_veu() edgeuse mate is bad edgeuse\n");
00340                 if (eu->eumate_p->eumate_p != eu)
00341                         rt_bomb("nmg_veu() edgeuse mate spurns edgeuse\n");
00342 
00343                 if (eu->radial_p->l.magic != NMG_EDGEUSE_MAGIC)
00344                         rt_bomb("nmg_veu() edgeuse radial is bad edgeuse\n");
00345                 if (eu->radial_p->radial_p != eu)
00346                         rt_bomb("nmg_veu() edgeuse radial denies knowing edgeuse\n");
00347 
00348                 nmg_vedge(eu->e_p, eu);
00349 
00350                 if( eu->vu_p->v_p != eu->eumate_p->vu_p->v_p )
00351                 {
00352                         if( !eu->l2.forw )
00353                                 rt_bomb("nmg_veu() l2.forw is NULL\n");
00354                         if( !eu->l2.back )
00355                                 rt_bomb("nmg_veu() l2.back is NULL\n");
00356 
00357                         if( eu->g.magic_p != eu->eumate_p->g.magic_p )
00358                                 rt_bomb("nmg_veu() edgeuse and mate don't share geometry\n");
00359                         if(eu->g.magic_p) nmg_veg(eu->g.magic_p);
00360                 }
00361 
00362                 switch (eu->orientation) {
00363                 case OT_NONE    : break;
00364                 case OT_SAME    : break;
00365                 case OT_OPPOSITE: break;
00366                 case OT_UNSPEC  : break;
00367                 default         : rt_bomb("nmg_veu() unknown loopuse orintation\n");
00368                                         break;
00369                 }
00370 
00371                 nmg_vvu(eu->vu_p, &eu->l.magic);
00372         }
00373 }
00374 
00375 /**
00376  *                      N M G _ V L G
00377  *
00378  *  Verify loop geometry
00379  */
00380 void
00381 nmg_vlg(const struct loop_g *lg)
00382 {
00383         int i;
00384 
00385         NMG_CK_LOOP_G(lg);
00386 
00387         for (i=0 ; i < ELEMENTS_PER_PT ; ++i)
00388                 if (lg->min_pt[i] > lg->max_pt[i])
00389                         rt_bomb("nmg_vlg() loop geom min_pt greater than max_pt\n");
00390 }
00391 
00392 /**
00393  *                      N M G _ V L O O P
00394  *
00395  *  Verify loop
00396  */
00397 void
00398 nmg_vloop(const struct loop *l, const struct loopuse *lup)
00399 {
00400 
00401         NMG_CK_LOOP(l);
00402         NMG_CK_LOOPUSE(lup);
00403 
00404         if (!l->lu_p) rt_bomb("nmg_vloop() null loopuse pointer\n");
00405 
00406 #if 0
00407         {
00408         struct loopuse *lu;
00409         for (lu=lup ; lu && lu != l->lu_p && lu->next != lup ; lu = lu->next);
00410 
00411         if (l->lu_p != lu)
00412                 for (lu=lup->lumate_p ; lu && lu != l->lu_p && lu->next != lup->lumate_p ; lu = lu->next);
00413 
00414         if (l->lu_p != lu) rt_bomb("nmg_vloop() can't get to parent loopuse from loop\n");
00415         }
00416 #endif
00417 
00418         if (l->lg_p) nmg_vlg(l->lg_p);
00419 }
00420 
00421 /**
00422  *                      N M G _ V L U
00423  *
00424  *  Verify loopuse
00425  */
00426 void
00427 nmg_vlu(const struct bu_list *hp, const long int *up)
00428 {
00429         struct loopuse *lu;
00430 
00431         for( BU_LIST_FOR( lu, loopuse, hp ) )  {
00432                 NMG_CK_LOOPUSE(lu);
00433 
00434                 if (lu->up.magic_p != up)  {
00435                         bu_log("nmg_vlu() up is x%x, s/b x%x\n",
00436                                 lu->up.magic_p, up );
00437                         rt_bomb("nmg_vlu() loopuse denies parentage\n");
00438                 }
00439 
00440                 if (!lu->l.forw)
00441                         rt_bomb("nmg_vlu() loopuse has null forw pointer\n");
00442                 if (BU_LIST_PNEXT_PLAST(loopuse,lu) != lu )
00443                         rt_bomb("nmg_vlu() forw loopuse has back pointing somewhere else\n");
00444 
00445                 if (!lu->lumate_p)
00446                         rt_bomb("nmg_vlu() loopuse has null mate pointer\n");
00447 
00448                 if (lu->lumate_p->l.magic != NMG_LOOPUSE_MAGIC)
00449                         rt_bomb("nmg_vlu() loopuse mate is bad loopuse\n");
00450 
00451                 if (lu->lumate_p->lumate_p != lu)
00452                         rt_bomb("nmg_vlu() lumate spurns loopuse\n");
00453 
00454                 switch (lu->orientation) {
00455                 case OT_NONE    : break;
00456                 case OT_SAME    : break;
00457                 case OT_OPPOSITE        : break;
00458                 case OT_UNSPEC  : break;
00459                 case OT_BOOLPLACE:      break;
00460                 default:
00461                         bu_log("lu=x%x, orientation=%d\n", lu, lu->orientation);
00462                         rt_bomb("nmg_vlu() unknown loopuse orintation\n");
00463                         break;
00464                 }
00465                 if (lu->lumate_p->orientation != lu->orientation)
00466                         rt_bomb("nmg_vlu() loopuse and mate have different orientation\n");
00467 
00468                 if (!lu->l_p)
00469                         rt_bomb("nmg_vlu() loopuse has Null loop pointer\n");
00470                 nmg_vloop(lu->l_p, lu);
00471 
00472                 if( BU_LIST_FIRST_MAGIC(&lu->down_hd) == NMG_EDGEUSE_MAGIC)
00473                         nmg_veu( &lu->down_hd, &lu->l.magic);
00474                 else if (BU_LIST_FIRST_MAGIC(&lu->down_hd) == NMG_VERTEXUSE_MAGIC)
00475                         nmg_vvu(BU_LIST_FIRST(vertexuse,&lu->down_hd), &lu->l.magic);
00476                 else
00477                         rt_bomb("nmg_vlu() bad down_hd magic\n");
00478         }
00479 }
00480 
00481 /**
00482  *                      N M G _ V F G
00483  *
00484  *  Verify face geometry
00485  */
00486 void
00487 nmg_vfg(const struct face_g_plane *fg)
00488 {
00489         NMG_CK_FACE_G_EITHER(fg);
00490 
00491         if( fg->magic == NMG_FACE_G_PLANE_MAGIC )
00492         {
00493                 if (fg->N[X]==0.0 && fg->N[Y]==0.0 && fg->N[Z]==0.0 &&
00494                     fg->N[H]!=0.0) {
00495                         bu_log("bad NMG plane equation %fX + %fY + %fZ = %f\n",
00496                                 fg->N[X], fg->N[Y], fg->N[Z], fg->N[H]);
00497                         rt_bomb("nmg_vfg() Bad NMG geometry\n");
00498                     }
00499         }
00500         if( fg->magic == NMG_FACE_G_SNURB_MAGIC )
00501         {
00502                 /* XXX Should the face's NURB be checked somehow?? */
00503         }
00504 }
00505 
00506 /**
00507  *                      N M G _ V F A C E
00508  *
00509  *  Verify face
00510  */
00511 void
00512 nmg_vface(const struct face *f, const struct faceuse *fup)
00513 {
00514         int             i;
00515 
00516         NMG_CK_FACE(f);
00517         NMG_CK_FACEUSE(fup);
00518 
00519         /* make sure we can get back to the parent faceuse from the face */
00520         if (!f->fu_p) rt_bomb("nmg_vface() null faceuse pointer\n");
00521 
00522 #if 0
00523         for (fu = fup; fu && fu != f->fu_p && fu->forw != fup; fu = fu->forw);
00524 
00525         if (f->fu_p != fu) rt_bomb("nmg_vface() can't get to parent faceuse from face\n");
00526 #endif
00527 
00528         for (i=0 ; i < ELEMENTS_PER_PT ; ++i)
00529                 if (f->min_pt[i] >= f->max_pt[i]) {
00530                         bu_log("nmg_vface() face min_pt[%d]:%g greater than max_pt[%d]:%g\n",
00531                                 i, f->min_pt[i], i, f->max_pt[i]);
00532                         bu_log("min_pt(%g %g %g)  ", V3ARGS(f->min_pt));
00533                         bu_log("max_pt(%g %g %g)\n", V3ARGS(f->max_pt));
00534                         rt_bomb("Invalid NMG\n");
00535                 }
00536         if (f->g.plane_p) nmg_vfg(f->g.plane_p);
00537 }
00538 
00539 /**
00540  *                      N M G _ V F U
00541  *
00542  *      Validate a list of faceuses
00543  */
00544 void
00545 nmg_vfu(const struct bu_list *hp, const struct shell *s)
00546 {
00547         struct faceuse *fu;
00548 
00549         NMG_CK_SHELL(s);
00550 
00551         for( BU_LIST_FOR( fu, faceuse, hp ) )  {
00552                 NMG_CK_FACEUSE(fu);
00553                 if (fu->s_p != s) {
00554                         bu_log("faceuse claims shell parent (%8x) instead of (%8x)\n",
00555                                 fu->s_p, s);
00556                         rt_bomb("nmg_vfu()\n");
00557                 }
00558 
00559                 if (!fu->l.forw) {
00560                         rt_bomb("nmg_vfu() faceuse forw is NULL\n");
00561                 } else if (fu->l.forw->back != (struct bu_list *)fu) {
00562                         rt_bomb("nmg_vfu() faceuse->forw->back != faceuse\n");
00563                 }
00564 
00565                 if (!fu->fumate_p)
00566                         rt_bomb("nmg_vfu() null faceuse fumate_p pointer\n");
00567 
00568                 if (fu->fumate_p->l.magic != NMG_FACEUSE_MAGIC)
00569                         rt_bomb("nmg_vfu() faceuse mate is bad faceuse ptr\n");
00570 
00571                 if (fu->fumate_p->fumate_p != fu)
00572                         rt_bomb("nmg_vfu() faceuse mate spurns faceuse!\n");
00573 
00574                 switch (fu->orientation) {
00575                 case OT_NONE    : break;
00576                 case OT_SAME    : if (fu->fumate_p->orientation != OT_OPPOSITE)
00577                                         rt_bomb("nmg_vfu() faceuse of \"SAME\" orientation has mate that is not \"OPPOSITE\" orientation\n");
00578                                 break;
00579                 case OT_OPPOSITE:  if (fu->fumate_p->orientation != OT_SAME)
00580                                         rt_bomb("nmg_vfu() faceuse of \"OPPOSITE\" orientation has mate that is not \"SAME\" orientation\n");
00581                                 break;
00582                 case OT_UNSPEC  : break;
00583                 default         : rt_bomb("nmg_vfu() unknown faceuse orintation\n"); break;
00584                 }
00585 
00586                 NMG_CK_FACE(fu->f_p);
00587                 nmg_vface(fu->f_p, fu);
00588 
00589                 nmg_vlu( &fu->lu_hd, &fu->l.magic);
00590         }
00591 }
00592 
00593 
00594 /**
00595  *                      N M G _ V S H E L L
00596  *
00597  *      validate a list of shells and all elements under them
00598  */
00599 void
00600 nmg_vshell(const struct bu_list *hp, const struct nmgregion *r)
00601 {
00602         struct shell *s;
00603         pointp_t lpt, hpt;
00604 
00605         NMG_CK_REGION(r);
00606 
00607         for( BU_LIST_FOR( s, shell, hp ) )  {
00608                 NMG_CK_SHELL(s);
00609                 if (s->r_p != r) {
00610                         bu_log("shell's r_p (%8x) doesn't point to parent (%8x)\n",
00611                                 s->r_p, r);
00612                         rt_bomb("nmg_vshell()\n");
00613                 }
00614 
00615                 if (!s->l.forw) {
00616                         rt_bomb("nmg_vshell(): Shell's forw ptr is null\n");
00617                 } else if (s->l.forw->back != (struct bu_list *)s) {
00618                         bu_log("forw shell's back(%8x) is not me (%8x)\n",
00619                                 s->l.forw->back, s);
00620                         rt_bomb("nmg_vshell()\n");
00621                 }
00622 
00623                 if (s->sa_p) {
00624                         NMG_CK_SHELL_A(s->sa_p);
00625                         /* we make sure that all values of min_pt
00626                          * are less than or equal to the values of max_pt
00627                          */
00628                         lpt = s->sa_p->min_pt;
00629                         hpt = s->sa_p->max_pt;
00630                         if (lpt[0] > hpt[0] || lpt[1] > hpt[1] ||
00631                             lpt[2] > hpt[2]) {
00632                                 bu_log("Bnmg_vshell() ad min_pt/max_pt for shell(%8x)'s extent\n");
00633                                 bu_log("Min_pt %g %g %g\n", lpt[0], lpt[1],
00634                                         lpt[2]);
00635                                 bu_log("Max_pt %g %g %g\n", hpt[0], hpt[1],
00636                                         hpt[2]);
00637                         }
00638                 }
00639 
00640                 /* now we check out the "children"
00641                  */
00642 
00643                 if (s->vu_p) {
00644                         if( BU_LIST_NON_EMPTY( &s->fu_hd ) ||
00645                             BU_LIST_NON_EMPTY( &s->lu_hd ) ||
00646                             BU_LIST_NON_EMPTY( &s->eu_hd ) )  {
00647                                 bu_log("shell (%8x) with vertexuse (%8x) has other children\n",
00648                                         s, s->vu_p);
00649                                 rt_bomb("nmg_vshell()\n");
00650                         }
00651                 }
00652 
00653                 nmg_vfu( &s->fu_hd, s);
00654                 nmg_vlu( &s->lu_hd, &s->l.magic);
00655                 nmg_veu( &s->eu_hd, &s->l.magic);
00656         }
00657 }
00658 
00659 
00660 
00661 /**
00662  *                      N M G _ V R E G I O N
00663  *
00664  *      validate a list of nmgregions and all elements under them
00665  */
00666 void
00667 nmg_vregion(const struct bu_list *hp, const struct model *m)
00668 {
00669         struct nmgregion *r;
00670 
00671         for( BU_LIST_FOR( r, nmgregion, hp ) )  {
00672                 NMG_CK_REGION(r);
00673                 if (r->m_p != m) {
00674                         bu_log("nmgregion pointer m_p %8x should be %8x\n",
00675                                 r->m_p, m);
00676                         rt_bomb("nmg_vregion()\n");
00677                 }
00678                 if (r->ra_p) {
00679                         NMG_CK_REGION_A(r->ra_p);
00680                 }
00681 
00682                 nmg_vshell( &r->s_hd, r);
00683 
00684                 if( BU_LIST_PNEXT_PLAST(nmgregion, r) != r )  {
00685                         rt_bomb("nmg_vregion() forw nmgregion's back is not me\n");
00686                 }
00687         }
00688 }
00689 
00690 /**
00691  *                      N M G _ V M O D E L
00692  *
00693  *      validate an NMG model and all elements in it.
00694  */
00695 void
00696 nmg_vmodel(const struct model *m)
00697 {
00698         NMG_CK_MODEL(m);
00699         nmg_vregion( &m->r_hd, m);
00700 }
00701 
00702 
00703 /************************************************************************
00704  *                                                                      *
00705  *                      Checking Routines                               *
00706  *                                                                      *
00707  ************************************************************************/
00708 
00709 /**
00710  *                      N M G _ C K _ E
00711  */
00712 void
00713 nmg_ck_e(const struct edgeuse *eu, const struct edge *e, const char *str)
00714 {
00715         char *errstr;
00716         struct edgeuse *eparent;
00717         errstr = bu_calloc(strlen(str)+128, 1, "nmg_ck_e error str");
00718         (void)sprintf(errstr, "%sedge %8lx\n", str, (unsigned long)e);
00719 
00720         NMG_CK_EDGE(e);
00721         NMG_CK_EDGEUSE(eu);
00722 
00723         eparent = e->eu_p;
00724 
00725         NMG_CK_EDGEUSE(eparent);
00726         NMG_CK_EDGEUSE(eparent->eumate_p);
00727         do {
00728                 if (eparent == eu || eparent->eumate_p == eu) break;
00729 
00730                 eparent = eparent->radial_p->eumate_p;
00731         } while (eparent != e->eu_p);
00732 
00733         if (eparent != eu && eparent->eumate_p != eu) rt_bomb(
00734                 strcat(errstr, "nmg_ck_e() Edge denies edgeuse parentage\n"));
00735 
00736         bu_free(errstr, "nmg_ck_e error str");
00737 }
00738 
00739 /**
00740  *                      N M G _ C K _ V U
00741  */
00742 void
00743 nmg_ck_vu(const long int *parent, const struct vertexuse *vu, const char *str)
00744 {
00745         char *errstr;
00746 
00747         errstr = bu_calloc(strlen(str)+128, 1, "nmg_ck_vu error str");
00748         (void)sprintf(errstr, "%svertexuse %8lx\n", str, (unsigned long)vu);
00749 
00750         if (vu->up.magic_p != parent) rt_bomb(
00751                 strcat(errstr, "nmg_ck_vu() Vertexuse denies parentage\n"));
00752 
00753         bu_free(errstr, "nmg_ck_vu error str");
00754 }
00755 
00756 /**
00757  *                      N M G _ C K _ E U
00758  */
00759 void
00760 nmg_ck_eu(const long int *parent, const struct edgeuse *eu, const char *str)
00761 {
00762         char *errstr;
00763         struct edgeuse *eur, *eu_next, *eu_last;
00764 
00765         errstr = bu_calloc(strlen(str)+128, 1, "nmg_ck_eu error str");
00766         (void)sprintf(errstr, "%sedgeuse %8lx\n", str, (unsigned long)eu);
00767 
00768         NMG_CK_EDGEUSE(eu);
00769 
00770         if (eu->up.magic_p != parent) rt_bomb(
00771                 strcat(errstr, "nmg_ck_eu() Edgeuse child denies parentage\n"));
00772 
00773         if (*eu->eumate_p->up.magic_p != *eu->up.magic_p) rt_bomb(
00774                 strcat(errstr, "nmg_ck_eu() eumate has differnt kind of parent\n"));
00775         if (*eu->up.magic_p == NMG_SHELL_MAGIC) {
00776                 if (eu->eumate_p->up.s_p != eu->up.s_p) rt_bomb(
00777                         strcat(errstr, "nmg_ck_eu() eumate in different shell\n"));
00778 
00779                 eur = eu->radial_p;
00780                 while (eur && eur != eu && eur != eu->eumate_p)
00781                         eur = eur->eumate_p->radial_p;
00782 
00783                 if (!eur) rt_bomb(strcat(errstr,
00784                         "nmg_ck_eu() Radial trip from eu ended in null pointer\n"));
00785 
00786 
00787         } else if (*eu->up.magic_p == NMG_LOOPUSE_MAGIC) {
00788                 if (eu->eumate_p->up.lu_p != eu->up.lu_p->lumate_p) rt_bomb(
00789                         strcat(errstr, "nmg_ck_eu() eumate not in same loop\n"));
00790 
00791                 eur = eu->radial_p;
00792                 while (eur && eur != eu->eumate_p && eur != eu)
00793                         eur = eur->eumate_p->radial_p;
00794 
00795                 if (!eur) rt_bomb(
00796                         strcat(errstr, "nmg_ck_eu() radial path leads to null ptr\n"));
00797                 if (eur == eu) rt_bomb(
00798                         strcat(errstr, "nmg_ck_eu() Never saw eumate\n"));
00799 
00800                 eu_next = BU_LIST_PNEXT_CIRC(edgeuse, eu);
00801                 if (eu_next->vu_p->v_p != eu->eumate_p->vu_p->v_p)
00802                         rt_bomb("nmg_ck_eu: next and mate don't share vertex\n");
00803 
00804                 eu_last = BU_LIST_PPREV_CIRC(edgeuse, eu);
00805                 if (eu_last->eumate_p->vu_p->v_p != eu->vu_p->v_p)
00806                         rt_bomb("nmg_ck_eu: edge and last-mate don't share vertex\n");
00807 
00808         } else {
00809                 rt_bomb(strcat(errstr, "nmg_ck_eu() Bad edgeuse parent\n"));
00810         }
00811 
00812         NMG_CK_EDGE(eu->e_p);
00813         nmg_ck_e(eu, eu->e_p, errstr);
00814 
00815         NMG_CK_VERTEXUSE(eu->vu_p);
00816         nmg_ck_vu(&eu->l.magic, eu->vu_p, errstr);
00817 
00818         bu_free(errstr, "nmg_ck_eu error str");
00819 }
00820 
00821 /**
00822  *                      N M G _ C K _ L G
00823  */
00824 void
00825 nmg_ck_lg(const struct loop *l, const struct loop_g *lg, const char *str)
00826 {
00827         char *errstr;
00828         errstr = bu_calloc(strlen(str)+128, 1, "nmg_ck_lg error str");
00829         (void)sprintf(errstr, "%sloop_g %8lx\n", str, (unsigned long)lg);
00830 
00831         NMG_CK_LOOP_G(lg);
00832         NMG_CK_LOOP(l);
00833 
00834         bu_free(errstr, "nmg_ck_lg error str");
00835 }
00836 
00837 /**
00838  *                      N M G _ C K _ L
00839  */
00840 void
00841 nmg_ck_l(const struct loopuse *lu, const struct loop *l, const char *str)
00842 {
00843         char *errstr;
00844         errstr = bu_calloc(strlen(str)+128, 1, "nmg_ck_l error str");
00845         (void)sprintf(errstr, "%sloop %8lx\n", str, (unsigned long)l);
00846 
00847         NMG_CK_LOOP(l);
00848         NMG_CK_LOOPUSE(lu);
00849 
00850         if (l->lu_p != lu && l->lu_p->lumate_p != lu) rt_bomb(
00851                 strcat(errstr, "nmg_ck_l() Cannot get from loop to loopuse\n"));
00852 
00853         if (l->lg_p) nmg_ck_lg(l, l->lg_p, errstr);
00854 
00855         bu_free(errstr, "");
00856 }
00857 
00858 /**
00859  *                      N M G _ C K _ L U
00860  */
00861 void
00862 nmg_ck_lu(const long int *parent, const struct loopuse *lu, const char *str)
00863 {
00864         struct edgeuse *eu;
00865         struct vertexuse *vu;
00866         char *errstr;
00867         int l;
00868         int edgeuse_num=0;
00869         long    magic1;
00870 
00871         errstr = bu_calloc(strlen(str)+128, 1, "nmg_ck_lu error str");
00872         (void)sprintf(errstr, "%sloopuse %8lx\n", str, (unsigned long)lu);
00873 
00874         NMG_CK_LOOPUSE(lu);
00875 
00876         if (lu->up.magic_p != parent) rt_bomb(
00877                 strcat(errstr, "nmg_ck_lu() loopuse child denies parentage\n") );
00878 
00879         /* check the parent of lu and lumate WRT each other */
00880         NMG_CK_LOOPUSE(lu->lumate_p);
00881         if (*lu->lumate_p->up.magic_p != *lu->up.magic_p) rt_bomb(
00882                 strcat(errstr,"nmg_ck_lu() loopuse mate has different kind of parent\n"));
00883 
00884         if (*lu->up.magic_p == NMG_SHELL_MAGIC) {
00885                 if (lu->lumate_p->up.s_p != lu->up.s_p) rt_bomb(
00886                         strcat(errstr, "nmg_ck_lu() Lumate not in same shell\n") );
00887         } else if (*lu->up.magic_p == NMG_FACEUSE_MAGIC) {
00888                 if (lu->lumate_p->up.fu_p != lu->up.fu_p->fumate_p) rt_bomb(
00889                         strcat(errstr, "nmg_ck_lu() lumate part of different face\n"));
00890         } else {
00891                 rt_bomb(strcat(errstr, "nmg_ck_lu() Bad loopuse parent type\n"));
00892         }
00893 
00894         NMG_CK_LOOP(lu->l_p);
00895         nmg_ck_l(lu, lu->l_p, errstr);
00896 
00897         /* check the children of the loopuse */
00898         magic1 = BU_LIST_FIRST_MAGIC( &lu->down_hd );
00899         if (magic1 == NMG_VERTEXUSE_MAGIC) {
00900                 vu = BU_LIST_FIRST( vertexuse, &lu->down_hd );
00901                 NMG_CK_VERTEXUSE(vu);
00902                 nmg_ck_vu(&lu->l.magic, vu, errstr);
00903         } else if (magic1 == NMG_EDGEUSE_MAGIC) {
00904                 l = strlen(errstr);
00905                 for( BU_LIST_FOR( eu, edgeuse, &lu->down_hd ) )  {
00906                         NMG_CK_EDGEUSE(eu);
00907                         (void)sprintf(&errstr[l], "%sedgeuse #%d (%8lx)\n",
00908                                 errstr, edgeuse_num++, (unsigned long)eu);
00909                         nmg_ck_eu(&lu->l.magic, eu, errstr);
00910                 }
00911         } else {
00912                 rt_bomb(strcat(errstr, "nmg_ck_lu() Bad loopuse down pointer\n") );
00913         }
00914         bu_free(errstr, "nmg_ck_lu error str");
00915 }
00916 
00917 /**
00918  *                      N M G _ C K _ F G
00919  */
00920 void
00921 nmg_ck_fg(const struct face *f, const struct face_g_plane *fg, const char *str)
00922 {
00923         char *errstr;
00924         errstr = bu_calloc(strlen(str)+128, 1, "nmg_ck_fg error str");
00925         (void)sprintf(errstr, "%sFace_g %8lx\n", str, (unsigned long)f);
00926 
00927         NMG_CK_FACE_G_PLANE(fg);
00928         if (fg->N[X]==0.0 && fg->N[Y]==0.0 && fg->N[Z]==0.0 && fg->N[H]!=0.0){
00929                 (void)sprintf(&errstr[strlen(errstr)],
00930                         "nmg_ck_fg() bad NMG plane equation %fX + %fY + %fZ = %f\n",
00931                         fg->N[X], fg->N[Y], fg->N[Z], fg->N[H]);
00932                 rt_bomb(errstr);
00933         }
00934 
00935         bu_free(errstr, "nmg_ck_fg error str");
00936 }
00937 
00938 /**
00939  *                      N M G _ C K _ F
00940  */
00941 void
00942 nmg_ck_f(const struct faceuse *fu, const struct face *f, const char *str)
00943 {
00944         char *errstr;
00945         errstr = bu_calloc(strlen(str)+128, 1, "nmg_ck_f error str");
00946         (void)sprintf(errstr, "%sFace %8lx\n", str, (unsigned long)f);
00947 
00948         NMG_CK_FACE(f);
00949         NMG_CK_FACEUSE(fu);
00950         NMG_CK_FACE_G_PLANE(f->g.plane_p);
00951         if (f->fu_p != fu && f->fu_p->fumate_p != fu) rt_bomb(
00952                 strcat(errstr,"nmg_ck_f() Cannot get from face to \"parent faceuse\"\n"));
00953 
00954         if (f->g.plane_p) nmg_ck_fg(f, f->g.plane_p, errstr);
00955 
00956         bu_free(errstr, "nmg_ck_f error str");
00957 }
00958 
00959 /**
00960  *                      N M G _ C K _ F U
00961  */
00962 void
00963 nmg_ck_fu(const struct shell *s, const struct faceuse *fu, const char *str)
00964 {
00965         char *errstr;
00966         int l;
00967         int loop_number = 0;
00968         struct loopuse *lu;
00969 
00970         NMG_CK_FACEUSE(fu);
00971         NMG_CK_SHELL(s);
00972 
00973         errstr = bu_calloc(strlen(str)+128, 1, "nmg_ck_fu error str");
00974         (void)sprintf(errstr, "%sFaceuse %8lx\n", str, (unsigned long)fu);
00975 
00976         if (fu->s_p != s) rt_bomb(
00977                 strcat(errstr, "nmg_ck_fu() faceuse child denies shell parentage\n") );
00978 
00979         if( BU_LIST_PNEXT_PLAST( faceuse, fu ) )
00980                 rt_bomb( strcat(errstr, "nmg_ck_fu() Faceuse not lastward of next faceuse\n") );
00981 
00982         if( BU_LIST_PLAST_PNEXT( faceuse, fu ) )
00983                 rt_bomb( strcat(errstr, "nmg_ck_fu() Faceuse not nextward from last faceuse\n") );
00984 
00985         NMG_CK_FACEUSE(fu->fumate_p);
00986         if (fu->fumate_p->fumate_p != fu) rt_bomb(
00987                 strcat(errstr, "nmg_ck_fu() Faceuse not fumate of fumate\n") );
00988 
00989         if (fu->fumate_p->s_p != s) rt_bomb(
00990                 strcat(errstr, "nmg_ck_fu() faceuse mates not in same shell\n") );
00991 
00992         nmg_ck_f(fu, fu->f_p, errstr);
00993 
00994         l = strlen(errstr);
00995         for( BU_LIST_FOR( lu, loopuse, &fu->lu_hd ) )  {
00996                 NMG_CK_LOOPUSE(lu);
00997                 (void)sprintf(&errstr[l] , "%sloopuse #%d (%8lx)\n",
00998                         errstr, loop_number++, (unsigned long)lu);
00999                 nmg_ck_lu(&fu->l.magic, lu, errstr);
01000         }
01001         bu_free(errstr, "nmg_ck_fu error str");
01002 }
01003 
01004 /**             N M G _ C K _ E G _ V E R T S
01005  *
01006  * Check if vertices from edgeuses using this edge geometry
01007  * actually lie on the edge geomatry.
01008  *
01009  * "eg" must be LSEG
01010  * returns number of vertices not on edge line
01011  */
01012 
01013 int
01014 nmg_ck_eg_verts(const struct edge_g_lseg *eg, const struct bn_tol *tol)
01015 {
01016         struct bu_list *eu2;
01017         vect_t e_dir;
01018         int count=0;
01019 
01020         NMG_CK_EDGE_G_LSEG( eg );
01021         BN_CK_TOL( tol );
01022 
01023         VMOVE( e_dir , eg->e_dir );
01024         VUNITIZE( e_dir );
01025 
01026         for( BU_LIST_FOR( eu2 , bu_list , &eg->eu_hd2 ) )
01027         {
01028                 struct edgeuse *eu;
01029                 struct vertex *v1,*v2;
01030                 struct vertex_g *vg1,*vg2;
01031                 vect_t pt_to_vert;
01032                 vect_t eg_to_vert;
01033 
01034                 eu = BU_LIST_MAIN_PTR( edgeuse, eu2, l2 );
01035 
01036                 NMG_CK_EDGEUSE( eu );
01037 
01038                 v1 = eu->vu_p->v_p;
01039                 NMG_CK_VERTEX( v1 );
01040                 vg1 = v1->vg_p;
01041                 NMG_CK_VERTEX_G( vg1 );
01042 
01043                 v2 = eu->eumate_p->vu_p->v_p;
01044                 NMG_CK_VERTEX( v2 );
01045                 vg2 = v2->vg_p;
01046                 NMG_CK_VERTEX_G( vg2 );
01047 
01048                 VSUB2( pt_to_vert , vg1->coord , eg->e_pt );
01049                 VJOIN1( eg_to_vert , pt_to_vert , -VDOT( e_dir , pt_to_vert ) , e_dir );
01050                 if( MAGSQ( eg_to_vert ) > tol->dist_sq )
01051                 {
01052                         count++;
01053                         bu_log( "vertex ( %g %g %g ) on eu to ( %g %g %g )\n", V3ARGS( vg1->coord ),
01054                                         V3ARGS( vg2->coord ) );
01055                         bu_log( "\tnot on edge geometry: pt=( %g %g %g ), dir=( %g %g %g )\n",
01056                                         V3ARGS( eg->e_pt ), V3ARGS( eg->e_dir ) );
01057                 }
01058         }
01059 
01060         return( count );
01061 }
01062 
01063 /**     N M G _ C K _ G E O M E T R Y
01064  *
01065  * Check that vertices actually lie on geometry for
01066  * faces and edges
01067  *
01068  * returns number of vertices that do not lie on geometry
01069  */
01070 int
01071 nmg_ck_geometry(const struct model *m, const struct bn_tol *tol)
01072 {
01073         struct bu_ptbl g_tbl;
01074         int i;
01075         int count=0;
01076 
01077         NMG_CK_MODEL( m );
01078         BN_CK_TOL( tol );
01079 
01080         bu_ptbl_init( &g_tbl , 64, " &g_tbl ");
01081 
01082         nmg_edge_g_tabulate( &g_tbl , &m->magic );
01083 
01084         for( i=0 ; i<BU_PTBL_END( &g_tbl ) ; i++ )
01085         {
01086                 long *ep;
01087                 struct edge_g_lseg *eg;
01088 
01089                 ep = BU_PTBL_GET( &g_tbl , i );
01090                 switch( *ep )
01091                 {
01092                         case NMG_EDGE_G_LSEG_MAGIC:
01093                                 eg = (struct edge_g_lseg *)ep;
01094                                 NMG_CK_EDGE_G_LSEG( eg );
01095                                 count += nmg_ck_eg_verts( eg , tol );
01096                                 break;
01097                         case NMG_EDGE_G_CNURB_MAGIC:
01098                                 /* XXX any checking for vertices on CNURB geometry?? */
01099                                 break;
01100                 }
01101         }
01102 
01103         bu_ptbl_reset( &g_tbl );
01104 
01105         nmg_face_tabulate( &g_tbl , &m->magic );
01106 
01107         for( i=0 ; i<BU_PTBL_END( &g_tbl ) ; i++ )
01108         {
01109                 struct face *f;
01110 
01111                 f = (struct face *)BU_PTBL_GET( &g_tbl , i );
01112                 NMG_CK_FACE( f );
01113 
01114                 count += nmg_ck_fg_verts( f->fu_p , f , tol );
01115         }
01116 
01117         bu_ptbl_free( &g_tbl );
01118 
01119         return( count );
01120 }
01121 
01122 /**
01123  *                      N M G _ C K _ F A C E _ W O R T H L E S S _ E D G E S
01124  *
01125  *  Search for null ("worthless") edges in a face.
01126  *  Such edges are legitimate to have, but can be troublesome
01127  *  for the boolean routines.
01128  *
01129  *  Often used to see if breaking an edge at a given
01130  *  vertex results in a null edge being created.
01131  */
01132 int
01133 nmg_ck_face_worthless_edges(const struct faceuse *fu)
01134 {
01135         const struct loopuse    *lu;
01136 
01137         for( BU_LIST_FOR( lu, loopuse, &fu->lu_hd ) )  {
01138                 struct edgeuse  *eu;
01139 
01140                 NMG_CK_LOOPUSE(lu);
01141                 if( BU_LIST_FIRST_MAGIC( &lu->down_hd ) == NMG_VERTEXUSE_MAGIC )
01142                         continue;
01143                 for( BU_LIST_FOR( eu, edgeuse, &lu->down_hd ) )  {
01144                         struct edgeuse          *neu;
01145                         neu = BU_LIST_PNEXT_CIRC( edgeuse, eu );
01146                         if( eu == neu )
01147                                 rt_bomb("nmg_ck_face_worthless_edges() lu has only one edge?\n");
01148                         if( eu->vu_p == neu->vu_p )
01149                                 rt_bomb("nmg_ck_face_worthless_edges() edge runs between two copies of vu??\n");
01150                         if( eu->vu_p->v_p == neu->vu_p->v_p )  {
01151 #if 0
01152                                 nmg_pr_eu( eu, NULL );
01153                                 nmg_pr_eu( neu, NULL );
01154 #endif
01155                                 bu_log("eu=x%x, neu=x%x, v=x%x\n", eu, neu, eu->vu_p->v_p);
01156                                 bu_log("eu=x%x, neu=x%x, v=x%x\n", eu->eumate_p, neu->eumate_p, eu->eumate_p->vu_p->v_p);
01157                                 rt_bomb("nmg_ck_face_worthless_edges() edge runs from&to same vertex\n");
01158                                 return 1;
01159                         }
01160                 }
01161         }
01162         return 0;
01163 
01164 }
01165 
01166 
01167 
01168 /**
01169  *                      N M G _ C K _ L U E U
01170  *
01171  *      check all the edgeuses of a loopuse to make sure these children
01172  *      know who thier parent really is.
01173  */
01174 void nmg_ck_lueu(const struct loopuse *cklu, const char *s)
01175 {
01176         struct edgeuse *eu;
01177 
01178         if (BU_LIST_FIRST_MAGIC(&cklu->down_hd) == NMG_VERTEXUSE_MAGIC)
01179                 rt_bomb("NMG nmg_ck_lueu.  I got a vertex loop!\n");
01180 
01181         eu = BU_LIST_FIRST(edgeuse, &cklu->down_hd);
01182         if (eu->l.back != &cklu->down_hd) {
01183                 rt_bomb("nmg_ck_lueu first element in list doesn't point back to head\n");
01184         }
01185 
01186         for (BU_LIST_FOR(eu, edgeuse, &cklu->down_hd)) {
01187                 NMG_CK_EDGEUSE(eu);
01188                 if (eu->up.lu_p != cklu) {
01189                         bu_log("nmg_cl_lueu() edgeuse of %s (going next) has lost proper parent\n", s);
01190                         rt_bomb("nmg_ck_lueu\n");
01191                 }
01192                 if ((struct edgeuse *)eu->l.forw->back != eu) {
01193                         bu_log("nmg_cl_lueu() %s next edge (%8x) doesn't point back to me (%8x)!\n", s, eu->l.forw, eu);
01194                         nmg_pr_lu(cklu, NULL);
01195                 }
01196                 if ((struct edgeuse *)eu->l.back->forw != eu) {
01197                         bu_log("nmg_cl_lueu() %s last edge (%8x) doesn't point forward to me (%8x)!\n", s, eu->l.forw, eu);
01198                         nmg_pr_lu(cklu, NULL);
01199                 }
01200         }
01201 
01202         cklu = cklu->lumate_p;
01203 
01204         eu = BU_LIST_FIRST(edgeuse, &cklu->down_hd);
01205         if (eu->l.back != &cklu->down_hd) {
01206                 rt_bomb("nmg_ck_lueu first element in lumate list doesn't point back to head\n");
01207         }
01208 
01209         for (BU_LIST_FOR(eu, edgeuse, &cklu->down_hd)) {
01210                 NMG_CK_EDGEUSE(eu);
01211                 if (eu->up.lu_p != cklu) {
01212                         bu_log("nmg_cl_lueu() edgeuse of %s (lumate going next) has lost proper parent\n", s);
01213                         rt_bomb("nmg_ck_lueu\n");
01214                 }
01215                 if ((struct edgeuse *)eu->l.forw->back != eu) {
01216                         bu_log("nmg_cl_lueu() %s next edge (%8x) doesn't point back to me (%8x)!\n", s, eu->l.forw, eu);
01217                         nmg_pr_lu(cklu, NULL);
01218                 }
01219                 if ((struct edgeuse *)eu->l.back->forw != eu) {
01220                         bu_log("nmg_cl_lueu() %s (lumate) back edge (%8x) doesn't point forward to me (%8x)!\n", s, eu->l.forw, eu);
01221                         nmg_pr_lu(cklu, NULL);
01222                 }
01223         }
01224 }
01225 
01226 /**
01227  *                      N M G _ C H E C K _ R A D I A L
01228  *
01229  *      check to see if all radial uses of an edge (within a shell) are
01230  *      properly oriented with respect to each other.
01231  *      NOTE that ONLY edgeuses belonging to the shell of eu are checked.
01232  *
01233  *      Can't check faceuse orientation parity for
01234  *      things from more than one shell;  parity is conserved
01235  *      only within faces from a single shell.
01236  *
01237  *  XXX Added code to skip dangling faces (needs to be checked a little more) - JRA
01238  *
01239  *  XXX I think that if dangling faces are to be processed correctly,
01240  *  XXX the caller should pass in a table of dangling faces.  -Mike
01241  *  XXX I've # if'ed that check out, for now.
01242  *
01243  *      Return
01244  *      0       OK
01245  *      1       bad edgeuse mate
01246  *      2       unclosed space
01247  */
01248 int
01249 nmg_check_radial(const struct edgeuse *eu, const struct bn_tol *tol)
01250 {
01251         const struct shell      *s;
01252 
01253         NMG_CK_EDGEUSE(eu);
01254         BN_CK_TOL(tol);
01255         s = nmg_find_s_of_eu(eu);
01256         NMG_CK_SHELL(s);
01257 
01258 #if 1
01259         /* Just use the new checker */
01260         return nmg_eu_radial_check( eu, s, tol );
01261 #else
01262         if (rt_g.NMG_debug & DEBUG_BASIC)  {
01263                 bu_log("nmg_check_radial(eu=x%x, tol)\n", eu);
01264         }
01265 
01266         eu_orig = eu;
01267         eu1 = eu;
01268 
01269         /* If this eu is a wire, advance to first non-wire (skipping dangling faces). */
01270         while( (fu = nmg_find_fu_of_eu(eu)) == (struct faceuse *)NULL ||
01271                 nmg_find_s_of_eu((struct edgeuse *)eu) != s
01272 #if BO_DANGLE
01273                 || nmg_dangling_face( fu, (char *)NULL )
01274 #endif
01275         )  {
01276                 eu = eu->radial_p->eumate_p;
01277                 if( eu == eu1 )  return 0;      /* wires all around */
01278         }
01279 
01280         curr_orient = fu->orientation;
01281         eur = eu->radial_p;
01282         eurstart = eur;
01283         eu1 = eu;                               /* virtual radial to eur */
01284 
01285         NMG_CK_EDGEUSE(eur);
01286         do {
01287                 /*
01288                  *  Search until another edgeuse in this shell is found.
01289                  *  Continue search if it is a wire edge or dangling face.
01290                  */
01291                 while( nmg_find_s_of_eu((struct edgeuse *)eur) != s  ||
01292                        (fu = nmg_find_fu_of_eu(eur)) == (struct faceuse *)NULL
01293 #if BO_DANGLE
01294                         || nmg_dangling_face( fu, (char *)NULL )
01295 #endif
01296                 )  {
01297                         /* Advance to next eur */
01298                         NMG_CK_EDGEUSE(eur->eumate_p);
01299                         if (eur->eumate_p->eumate_p != eur) {
01300                                 rt_bomb("nmg_check_radial: bad edgeuse mate\n");
01301                         }
01302                         eur = eur->eumate_p->radial_p;
01303                         NMG_CK_EDGEUSE(eur);
01304                         if( eur == eurstart )  return 0;
01305                 }
01306 
01307                 /* if that radial edgeuse doesn't have the
01308                  * correct orientation, print & bomb
01309                  * If radial (eur) is my (virtual, this-shell) mate (eu1),
01310                  * then it's ok, a mis-match is to be expected.
01311                  */
01312                 NMG_CK_LOOPUSE(eur->up.lu_p);
01313                 fu = eur->up.lu_p->up.fu_p;
01314                 NMG_CK_FACEUSE(fu);
01315                 if (fu->orientation != curr_orient &&
01316                     eur != eu1->eumate_p ) {
01317                         char file[128];
01318                         char buf[128];
01319                         static int num=0;
01320 
01321                         p = eu1->vu_p->v_p->vg_p->coord;
01322                         q = eu1->eumate_p->vu_p->v_p->vg_p->coord;
01323                         bu_log("nmg_check_radial(): Radial orientation problem\n  edge: %g %g %g -> %g %g %g\n",
01324                                 p[0], p[1], p[2], q[0], q[1], q[2]);
01325                         bu_log("  eu_orig=%8x, eur=%8x, s=x%x, eurstart=x%x, curr_orient=%s\n",
01326                                 eu_orig, eur, s, eurstart,
01327                                 nmg_orientation(curr_orient) );
01328 
01329                         /* Plot the edge in yellow, & the loops */
01330                         rt_g.NMG_debug |= DEBUG_PLOTEM;
01331                         nmg_face_lu_plot( eu1->up.lu_p, eu1->vu_p,
01332                                 eu1->eumate_p->vu_p );
01333                         nmg_face_lu_plot( eur->up.lu_p, eur->vu_p,
01334                                 eur->eumate_p->vu_p );
01335 
01336                         sprintf(buf, "%g %g %g -> %g %g %g\n",
01337                                 p[0], p[1], p[2], q[0], q[1], q[2]);
01338 
01339                         sprintf(file, "radial%d.g", num++);
01340                         nmg_stash_model_to_file( file,
01341                                 nmg_find_model(&(fu->l.magic)), buf);
01342 
01343                         nmg_pr_fu_around_eu( eu_orig, tol );
01344 
01345                         bu_log("nmg_check_radial: unclosed space\n");
01346                         return(2);
01347                 }
01348 
01349                 eu1 = eur->eumate_p;
01350                 NMG_CK_LOOPUSE(eu1->up.lu_p);
01351                 NMG_CK_FACEUSE(eu1->up.lu_p->up.fu_p);
01352                 curr_orient = eu1->up.lu_p->up.fu_p->orientation;
01353                 eur = eu1->radial_p;
01354         } while (eur != eurstart);
01355         return(0);
01356 #endif
01357 }
01358 
01359 /**
01360  *                      N M G _ E U _ 2 S _ O R I E N T _ B A D
01361  *
01362  *  Given an edgeuse, check that the proper orientation "parity" of
01363  *  same/opposite/opposite/same is preserved, for all non-wire edgeuses
01364  *  within shell s1.
01365  *  If s2 is non-null, then ensure that the parity of all edgeuses in
01366  *  BOTH s1 and s2 are correct, and mutually compatible.
01367  *
01368  *  This routine does not care if a face is "dangling" or not.
01369  *
01370  *  If the edgeuse specified is a wire edgeuse, skip forward to a non-wire.
01371  *
01372  *  Returns -
01373  *      0       OK
01374  *      !0      Bad orientation parity.
01375  */
01376 int
01377 nmg_eu_2s_orient_bad(const struct edgeuse *eu, const struct shell *s1, const struct shell *s2, const struct bn_tol *tol)
01378 {
01379         char                    curr_orient;
01380         const struct edgeuse    *eu_orig;
01381         const struct edgeuse    *eur;
01382         const struct edgeuse    *eu1;
01383         const struct edgeuse    *eurstart;
01384         const struct faceuse    *fu;
01385         const struct shell      *s;
01386         int                     ret = 0;
01387 
01388         NMG_CK_EDGEUSE(eu);
01389         NMG_CK_SHELL(s1);
01390         if(s2) NMG_CK_SHELL(s2);        /* s2 may be NULL */
01391         BN_CK_TOL(tol);
01392 
01393         eu_orig = eu;                   /* for printing */
01394         eu1 = eu;                       /* remember, for loop termination */
01395 
01396         /*
01397          *  If this eu is not in s1, or it is a wire,
01398          *  advance to first non-wire.
01399          */
01400         for(;;)  {
01401                 fu = nmg_find_fu_of_eu(eu);
01402                 if( !fu ) goto next_a;          /* it's a wire */
01403                 s = fu->s_p;
01404                 NMG_CK_SHELL(s);
01405                 if( s != s1 )  goto next_a;
01406                 break;
01407 next_a:
01408                 eu = eu->radial_p->eumate_p;
01409                 if( eu == eu1 )  goto out;      /* wires all around */
01410         }
01411 
01412         curr_orient = fu->orientation;
01413         eur = eu->radial_p;
01414         eurstart = eur;
01415         eu1 = eu;                               /* virtual radial to eur */
01416 
01417         NMG_CK_EDGEUSE(eur);
01418         do {
01419                 /*
01420                  *  Search until another edgeuse in shell s1 or s2 is found.
01421                  *  Continue search if it is a wire edge or dangling face.
01422                  */
01423                 for(;;)  {
01424                         fu = nmg_find_fu_of_eu(eur);
01425                         if( !fu ) goto next_eu;         /* it's a wire */
01426                         NMG_CK_FACEUSE(fu);
01427                         s = fu->s_p;
01428                         NMG_CK_SHELL(s);
01429                         if( s != s1 )  {
01430                                 if( !s2 )  goto next_eu;
01431                                 if( s != s2 )  goto next_eu;
01432                         }
01433                         break;
01434 next_eu:
01435                         /* Advance to next eur */
01436                         NMG_CK_EDGEUSE(eur->eumate_p);
01437                         if (eur->eumate_p->eumate_p != eur)
01438                                 rt_bomb("nmg_eu_2s_orient_bad: bad edgeuse mate\n");
01439 
01440                         eur = eur->eumate_p->radial_p;
01441                         NMG_CK_EDGEUSE(eur);
01442                         if( eur == eurstart )  goto out;
01443                 }
01444 
01445                 /*
01446                  *  eur is mate's radial of last eu.
01447                  *  If the orientation does not match, this is an error.
01448                  *  If radial (eur) is my (virtual, this-shell) mate (eu1),
01449                  *  then it's OK, a mis-match is to be expected when there
01450                  *  is only one edgeuse&mate from this shell on this edge.
01451                  */
01452                 if (fu->orientation != curr_orient &&
01453                     eur != eu1->eumate_p ) {
01454                         nmg_pr_fu_around_eu( eu_orig, tol );
01455                         bu_log("nmg_eu_2s_orient_bad(eu=x%x, s1=x%x, s2=x%x) bad radial parity eu1=x%x, eur=x%x, eurstart=x%x\n",
01456                                 eu_orig, s1, s2, eu1, eur, eurstart);
01457                         ret = 1;
01458                         goto out;
01459                 }
01460 
01461                 /* If eu belongs to a face, eumate had better, also! */
01462                 eu1 = eur->eumate_p;
01463                 NMG_CK_LOOPUSE(eu1->up.lu_p);
01464                 fu = eu1->up.lu_p->up.fu_p;
01465                 NMG_CK_FACEUSE(fu);
01466                 curr_orient = fu->orientation;
01467                 eur = eu1->radial_p;
01468         } while (eur != eurstart);
01469         /* All is well, the whole way 'round */
01470 out:
01471         if (rt_g.NMG_debug & DEBUG_BASIC)  {
01472                 bu_log("nmg_eu_2s_orient_bad(eu=x%x, s1=x%x, s2=x%x) ret=%d\n",
01473                         eu_orig, s1, s2, ret);
01474         }
01475         return ret;
01476 }
01477 
01478 /**
01479  *                      N M G _ C K _ C L O S E D _ S U R F
01480  *
01481  *  Verify that shell is closed.
01482  *  Do this by verifying that it is not possible to get from outside
01483  *  to inside the solid by crossing any face edge.
01484  *
01485  *  Returns -
01486  *       0      OK
01487  *      !0      Problem.
01488  */
01489 int
01490 nmg_ck_closed_surf(const struct shell *s, const struct bn_tol *tol)
01491 {
01492         struct faceuse *fu;
01493         struct loopuse *lu;
01494         struct edgeuse *eu;
01495         int             status = 0;
01496         long            magic1;
01497 
01498         NMG_CK_SHELL(s);
01499         BN_CK_TOL(tol);
01500         for( BU_LIST_FOR( fu, faceuse, &s->fu_hd ) )  {
01501                 NMG_CK_FACEUSE(fu);
01502                 for( BU_LIST_FOR( lu, loopuse, &fu->lu_hd ) )  {
01503                         NMG_CK_LOOPUSE(lu);
01504                         magic1 = BU_LIST_FIRST_MAGIC( &lu->down_hd );
01505                         if (magic1 == NMG_EDGEUSE_MAGIC) {
01506                                 /* Check status on all the edgeuses before quitting */
01507                                 for( BU_LIST_FOR( eu, edgeuse, &lu->down_hd ) )  {
01508                                         if (nmg_check_radial(eu, tol))
01509                                                 status = 1;
01510                                 }
01511                                 if( status )  {
01512                                         bu_log("nmg_ck_closed_surf(x%x), problem with loopuse x%x\n", s, lu);
01513                                         return 1;
01514                                 }
01515                         } else if (magic1 == NMG_VERTEXUSE_MAGIC) {
01516                                 register struct vertexuse       *vu;
01517                                 vu = BU_LIST_FIRST( vertexuse, &lu->down_hd );
01518                                 NMG_CK_VERTEXUSE(vu);
01519                                 NMG_CK_VERTEX(vu->v_p);
01520                         }
01521                 }
01522         }
01523         return(0);
01524 }
01525 
01526 /**
01527  *                      N M G _ C K _ C L O S E D _ R E G I O N
01528  *
01529  *  Check all the shells in a region for being closed.
01530  *
01531  *  Returns -
01532  *       0      OK
01533  *      !0      status code from nmg_check_radial()
01534  */
01535 int
01536 nmg_ck_closed_region(const struct nmgregion *r, const struct bn_tol *tol)
01537 {
01538         const struct shell      *s;
01539         int             ret;
01540 
01541         NMG_CK_REGION(r);
01542         BN_CK_TOL(tol);
01543         for( BU_LIST_FOR( s, shell, &r->s_hd ) )  {
01544                 ret = nmg_ck_closed_surf( s, tol );
01545                 if( ret != 0 )  return(ret);
01546         }
01547         return(0);
01548 }
01549 
01550 /**     N M G _ C K _ V _ I N _ 2 F U S
01551  *
01552  *      accepts a vertex pointer, two faceuses, and a tolerance.
01553  *      Checks if the vertex is in both faceuses (topologically
01554  *      and geometrically within tolerance of plane).
01555  *
01556  *      Calls rt_bomb if vertex is not in the faceuses topology or
01557  *      out of tolerance of either face.
01558  *
01559  */
01560 
01561 void
01562 nmg_ck_v_in_2fus(const struct vertex *vp, const struct faceuse *fu1, const struct faceuse *fu2, const struct bn_tol *tol)
01563 {
01564         struct bu_vls str;
01565         struct faceuse *fu;
01566         struct vertexuse *vu;
01567         fastf_t dist1,dist2;
01568         int found1=0,found2=0;
01569         plane_t n1, n2;
01570 
01571         NMG_CK_VERTEX( vp );
01572         NMG_CK_FACEUSE( fu1 );
01573         NMG_CK_FACEUSE( fu2 );
01574         BN_CK_TOL( tol );
01575 
01576         /* topology check */
01577         for( BU_LIST_FOR( vu , vertexuse , &vp->vu_hd ) )
01578         {
01579                 fu = nmg_find_fu_of_vu( vu );
01580                 if( fu == fu1 )
01581                         found1 = 1;
01582                 if( fu == fu2 )
01583                         found2 = 1;
01584                 if( found1 && found2 )
01585                         break;
01586         }
01587 
01588         if( !found1 || !found2 )
01589         {
01590                 bu_vls_init( &str );
01591                 bu_vls_printf( &str , "nmg_ck_v_in_2fus: vertex x%lx not used in" , (long)vp );
01592                 if( !found1 )
01593                         bu_vls_printf( &str , " faceuse x%lx" , (long)fu1 );
01594                 if( !found2 )
01595                         bu_vls_printf( &str , " faceuse x%lx" , (long)fu2 );
01596                 rt_bomb( bu_vls_addr( &str ) );
01597         }
01598 
01599         /* geometry check */
01600         NMG_GET_FU_PLANE(n1, fu1);
01601         NMG_GET_FU_PLANE(n2, fu2);
01602         dist1 = DIST_PT_PLANE( vp->vg_p->coord , n1 );
01603         dist2 = DIST_PT_PLANE( vp->vg_p->coord , n2 );
01604 
01605         if( !NEAR_ZERO( dist1 , tol->dist ) || !NEAR_ZERO( dist2 , tol->dist ) )
01606         {
01607                 bu_vls_init( &str );
01608                 bu_vls_printf( &str , "nmg_ck_v_in_2fus: vertex x%lx ( %g %g %g ) not in plane of" ,
01609                                 (long)vp , V3ARGS( vp->vg_p->coord ) );
01610                 if( !NEAR_ZERO( dist1 , tol->dist ) )
01611                         bu_vls_printf( &str , " faceuse x%lx (off by %g)" , (long)fu1 , dist1 );
01612                 if( !NEAR_ZERO( dist2 , tol->dist ) )
01613                         bu_vls_printf( &str , " faceuse x%lx (off by %g)" , (long)fu2 , dist2 );
01614                 rt_bomb( bu_vls_addr( &str ) );
01615         }
01616 
01617 }
01618 /**     N M G _ C K _ V S _ I N _ R E G I O N
01619  *
01620  *      Visits every vertex in the region and checks if the
01621  *      vertex coordinates are within tolerance of every face
01622  *      it is supposed to be in (according to the topology).
01623  *
01624  */
01625 
01626 struct v_ck_state {
01627         char            *visited;
01628         struct bu_ptbl *tabl;
01629         struct bn_tol   *tol;
01630 };
01631 
01632 static void
01633 nmg_ck_v_in_fus(long int *vp, genptr_t state, int first)
01634 {
01635         register struct v_ck_state *sp = (struct v_ck_state *)state;
01636         register struct vertex  *v = (struct vertex *)vp;
01637 
01638         NMG_CK_VERTEX(v);
01639         /* If this vertex has been processed before, do nothing more */
01640         if( NMG_INDEX_FIRST_TIME(sp->visited, v) )
01641         {
01642                 struct vertexuse *vu;
01643                 struct faceuse *fu;
01644 
01645                 for( BU_LIST_FOR( vu , vertexuse , &v->vu_hd ) )
01646                 {
01647                         fastf_t dist;
01648 
01649                         fu = nmg_find_fu_of_vu( vu );
01650                         if( fu )
01651                         {
01652                                 plane_t         n;
01653 
01654                                 NMG_CK_FACEUSE( fu );
01655                                 if( fu->orientation != OT_SAME )
01656                                         continue;
01657                                 if( !fu->f_p->g.magic_p )
01658                                         bu_log( "ERROR - nmg_ck_vs_in_region: fu (x%x) has no geometry\n", fu );
01659                                 else if( *fu->f_p->g.magic_p == NMG_FACE_G_PLANE_MAGIC )
01660                                 {
01661                                         NMG_GET_FU_PLANE( n, fu );
01662                                         dist = DIST_PT_PLANE( v->vg_p->coord , n );
01663                                         if( !NEAR_ZERO( dist , sp->tol->dist ) )
01664                                         {
01665                                                 bu_log( "ERROR - nmg_ck_vs_in_region: vertex x%x ( %g %g %g ) is %g from faceuse x%x\n" ,
01666                                                         v , V3ARGS( v->vg_p->coord ) , dist , fu );
01667                                         }
01668                                 }
01669                                 /* else if( *fu->f_p->g.magic_p == NMG_FACE_G_SNURB_MAGIC ) XXXX */
01670                         }
01671                 }
01672         }
01673 }
01674 
01675 void
01676 nmg_ck_vs_in_region(const struct nmgregion *r, const struct bn_tol *tol)
01677 {
01678         struct model                    *m;
01679         struct v_ck_state               st;
01680         struct bu_ptbl                  tab;
01681         static const struct nmg_visit_handlers handlers = {NULL, NULL, NULL, NULL, NULL,
01682                                                            NULL, NULL, NULL, NULL, NULL,
01683                                                            NULL, NULL, NULL, NULL, NULL,
01684                                                            NULL, NULL, NULL, NULL, NULL,
01685                                                            NULL, NULL, NULL, nmg_ck_v_in_fus, NULL};
01686         /* handlers.vis_vertex = nmg_ck_v_in_fus; */
01687 
01688         NMG_CK_REGION(r);
01689         BN_CK_TOL( tol );
01690         m = r->m_p;
01691         NMG_CK_MODEL(m);
01692 
01693         st.visited = (char *)bu_calloc(m->maxindex+1, sizeof(char), "visited[]");
01694         st.tabl = &tab;
01695         st.tol = (struct bn_tol *)tol;
01696 
01697         (void)bu_ptbl_init( &tab, 64, " &tab");
01698 
01699         nmg_visit( &r->l.magic, &handlers, (genptr_t)&st );
01700 
01701         bu_ptbl_free( &tab );
01702 
01703         bu_free( (char *)st.visited, "visited[]");
01704 }
01705 
01706 /*
01707  * Local Variables:
01708  * mode: C
01709  * tab-width: 8
01710  * c-basic-offset: 4
01711  * indent-tabs-mode: t
01712  * End:
01713  * ex: shiftwidth=4 tabstop=8
01714  */

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