bigE.c

Go to the documentation of this file.
00001 /*                          B I G E . C
00002  * BRL-CAD
00003  *
00004  * Copyright (c) 1997-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 ray */
00023 /*@{*/
00024 /** @file bigE.c
00025  * This module implements the 'E' command.
00026  *
00027  *  Author -
00028  *      John Anderson
00029  *
00030  *  Modifications -
00031  *      Bob Parker - modified to live in librt's drawable geometry object.
00032  *
00033  *  Source -
00034  *      The U. S. Army Ballistic Research Laboratory
00035  *      Aberdeen Proving Ground, Maryland  21005-5066
00036  *
00037  */
00038 /*@}*/
00039 
00040 #ifndef lint
00041 static const char RCSid[] = "";
00042 #endif
00043 
00044 #include "common.h"
00045 
00046 #include <stdlib.h>
00047 #include <stdio.h>
00048 #include <signal.h>
00049 #ifdef HAVE_STRING_H
00050 #  include <string.h>
00051 #else
00052 #  include <strings.h>
00053 #endif
00054 #include <errno.h>
00055 #include <time.h>
00056 
00057 #include "machine.h"
00058 #include "bu.h"
00059 #include "vmath.h"
00060 #include "nmg.h"
00061 #include "rtgeom.h"
00062 #include "raytrace.h"
00063 #include "solid.h"
00064 #include <ctype.h>
00065 /* #define debug 1 */
00066 
00067 struct dg_client_data {
00068         struct dg_obj           *dgop;
00069         Tcl_Interp              *interp;
00070         int                     wireframe_color_override;
00071         int                     wireframe_color[3];
00072         struct application      *ap;
00073         struct bu_ptbl          leaf_list;
00074         struct rt_i             *rtip;
00075         time_t                  start_time;
00076         time_t                  etime;
00077         long                    nvectors;
00078         int                     do_polysolids;
00079         int                     num_halfs;
00080 };
00081 
00082 union E_tree *build_etree(union tree *tp, struct dg_client_data *dgcdp);
00083 
00084 /* segment types (stored in the "seg_stp" field of the (struct seg) */
00085 #define ON_SURF (struct soltab *)0x1
00086 #define IN_SOL  (struct soltab *)0x2
00087 #define ON_INT  (struct soltab *)0x3
00088 
00089 #define NOT_SEG_OVERLAP( _a, _b )       ((_a->seg_out.hit_dist <= _b->seg_in.hit_dist) || (_b->seg_out.hit_dist <= _a->seg_in.hit_dist))
00090 
00091 /* RT_FREE_SEG_LIST assumed list head is a "struct seg" */
00092 #define MY_FREE_SEG_LIST( _segheadp, _res )     { \
00093         register struct seg *_a; \
00094         while( BU_LIST_WHILE( _a, seg, (_segheadp) ) )  { \
00095                 BU_LIST_DEQUEUE( &(_a->l) ); \
00096                 RT_FREE_SEG( _a, _res ); \
00097         } }
00098 
00099 /* stolen from g_half.c */
00100 struct half_specific  {
00101         plane_t half_eqn;               /* Plane equation, outward normal */
00102         vect_t  half_Xbase;             /* "X" basis direction */
00103         vect_t  half_Ybase;             /* "Y" basis direction */
00104 };
00105 #define HALF_NULL       ((struct half_specific *)0)
00106 
00107 /* structures for building a tree corresponding to the region to be drawn
00108  * uses the same "op" values as "union tree"
00109  */
00110 union E_tree
00111 {
00112         long magic;
00113 
00114         struct E_node   /* the operator nodes */
00115         {
00116                 long magic;
00117                 int op;
00118                 union E_tree *left;
00119                 union E_tree *right;
00120         } n;
00121 
00122         struct E_leaf   /* the leaf nodes */
00123         {
00124                 long magic;
00125                 int op;
00126                 struct model *m;                /* NMG version of this leaf solid */
00127                 struct bu_list seghead;         /* head of list of segments for this leaf solid */
00128                 struct bu_ptbl edge_list;       /* list of edges from above NMG */
00129                 struct soltab *stp;             /* the usual soltab pointer */
00130                 unsigned char do_not_free_model; /* A flag indicating that the NMG model pointer is a reference to the
00131                                                  * NMG model in the soltab structure */
00132         } l;
00133 };
00134 
00135 #define E_TREE_MAGIC            0x45545245
00136 #define CK_ETREE(_p)            BU_CKMAG( _p, E_TREE_MAGIC, "struct E_tree" )
00137 
00138 void
00139 Edrawtree(int dp)
00140 {
00141         return;
00142 }
00143 
00144 HIDDEN union E_tree *
00145 #if 1
00146 add_solid(const struct directory        *dp,
00147           matp_t                        mat,
00148           struct dg_client_data         *dgcdp)
00149 #else
00150 add_solid(dp, mat, dgcdp)
00151 struct directory *dp;
00152 matp_t mat;
00153 struct dg_client_data *dgcdp;
00154 #endif
00155 {
00156         union E_tree *eptr;
00157         struct nmgregion *r;
00158         struct rt_db_internal intern;
00159         int id;
00160         int solid_is_plate_mode_bot=0;
00161 
00162         BU_GETUNION( eptr, E_tree );
00163         eptr->magic = E_TREE_MAGIC;
00164 
00165         id = rt_db_get_internal( &intern, dp, dgcdp->dgop->dgo_wdbp->dbip, mat, &rt_uniresource );
00166         if( id < 0 )
00167         {
00168                 Tcl_AppendResult(dgcdp->interp, "Failed to get internal form of ",
00169                         dp->d_namep, "\n", (char *)NULL );
00170                 eptr->l.m = (struct model *)NULL;
00171                 return( eptr );
00172         }
00173         if( id == ID_COMBINATION )
00174         {
00175                 /* do explicit expansion of referenced combinations */
00176 
00177                 struct rt_comb_internal *comb;
00178 
00179                 bu_free( (char *)eptr, "eptr" );
00180 
00181                 comb = (struct rt_comb_internal *)intern.idb_ptr;
00182                 RT_CK_COMB( comb );
00183 
00184                 eptr = build_etree( comb->tree, dgcdp );
00185                 rt_db_free_internal( &intern, &rt_uniresource );
00186                 return( eptr );
00187         }
00188 #if 0
00189         if( id == ID_BOT )
00190         {
00191                 struct rt_bot_internal *bot = (struct rt_bot_internal *)intern.idb_ptr;
00192 
00193                 /* if this is a plate mode BOT, lie to the tesselator to get
00194                  * an approximation
00195                  */
00196 
00197                 RT_BOT_CK_MAGIC( bot );
00198 
00199                 if( bot->mode == RT_BOT_PLATE || bot->mode == RT_BOT_PLATE_NOCOS )
00200                 {
00201                         solid_is_plate_mode_bot = 1;
00202                         bot->mode = RT_BOT_SOLID;
00203                 }
00204         }
00205 #endif
00206         if( id == ID_HALF )
00207         {
00208                 eptr->l.m = NULL;
00209                 dgcdp->num_halfs++;
00210         }
00211         else if( id == ID_NMG )
00212         {
00213                 /* steal the nmg model */
00214                 eptr->l.m = (struct model *)intern.idb_ptr;
00215                 eptr->l.do_not_free_model = 1;
00216         }
00217         else
00218         {
00219                 /* create the NMG version of this solid */
00220                 eptr->l.m = nmg_mm();
00221                 if (rt_functab[id].ft_tessellate( &r, eptr->l.m, &intern,
00222                         &dgcdp->dgop->dgo_wdbp->wdb_ttol, &dgcdp->dgop->dgo_wdbp->wdb_tol) < 0)
00223                 {
00224                         nmg_km( eptr->l.m );
00225                         eptr->l.m = NULL;
00226                 }
00227         }
00228 
00229         /* get the soltab stuff */
00230         BU_GETSTRUCT( eptr->l.stp, soltab );
00231         eptr->l.stp->l.magic = RT_SOLTAB_MAGIC;
00232         eptr->l.stp->l2.magic = RT_SOLTAB2_MAGIC;
00233         eptr->l.stp->st_dp = dp;
00234         eptr->l.stp->st_matp = mat;
00235 
00236         {
00237                 struct rt_bot_internal *bot;
00238                 struct rt_db_internal intern2;
00239 
00240                 if( dgcdp->do_polysolids )
00241                 {
00242                         struct shell *s=(struct shell *)NULL;
00243                         struct nmgregion *r=(struct nmgregion *)NULL;
00244 
00245                         /* create and prep a BoT version of this solid */
00246                         if( eptr->l.m ) {
00247                                 r = BU_LIST_FIRST( nmgregion, &eptr->l.m->r_hd );
00248                                 s = BU_LIST_FIRST( shell, &r->s_hd );
00249                         }
00250 
00251                         if( solid_is_plate_mode_bot ||
00252                             !eptr->l.m ||
00253                             (bot=nmg_bot( s, &dgcdp->dgop->dgo_wdbp->wdb_tol ) ) == (struct rt_bot_internal *)NULL )
00254                         {
00255                                 eptr->l.stp->st_id = id;
00256                                 eptr->l.stp->st_meth = &rt_functab[id];
00257                                 if( rt_functab[id].ft_prep( eptr->l.stp, &intern, dgcdp->rtip ) < 0 )
00258                                         Tcl_AppendResult(dgcdp->interp, "Prep failure for solid '", dp->d_namep,
00259                                                 "'\n", (char *)NULL );
00260                         }
00261                         else
00262                         {
00263                                 RT_INIT_DB_INTERNAL( &intern2 );
00264                                 intern2.idb_major_type = DB5_MAJORTYPE_BRLCAD;
00265                                 intern2.idb_type = ID_BOT;
00266                                 intern2.idb_meth = &rt_functab[ID_BOT];
00267                                 intern2.idb_ptr = (genptr_t)bot;
00268                                 eptr->l.stp->st_id = ID_BOT;
00269                                 eptr->l.stp->st_meth = &rt_functab[ID_BOT];
00270                                 if (rt_functab[ID_BOT].ft_prep( eptr->l.stp, &intern2, dgcdp->rtip ) < 0 )
00271                                 {
00272                                         Tcl_AppendResult(dgcdp->interp, "Prep failure for solid '", dp->d_namep,
00273                                                          "'\n", (char *)NULL );
00274                                 }
00275 
00276                                 rt_db_free_internal( &intern2, &rt_uniresource );
00277                         }
00278                 }
00279                 else
00280                 {
00281                         /* prep this solid */
00282 
00283                         eptr->l.stp->st_id = id;
00284                         eptr->l.stp->st_meth = &rt_functab[id];
00285                         if( rt_functab[id].ft_prep( eptr->l.stp, &intern, dgcdp->rtip ) < 0 )
00286                                 Tcl_AppendResult(dgcdp->interp, "Prep failure for solid '", dp->d_namep,
00287                                         "'\n", (char *)NULL );
00288                 }
00289         }
00290 
00291         if( id != ID_NMG )
00292                 rt_db_free_internal( &intern, &rt_uniresource );
00293 
00294         /* add this leaf to the leaf list */
00295         bu_ptbl_ins( &dgcdp->leaf_list, (long *)eptr );
00296 
00297         return( eptr );
00298 }
00299 
00300 /* build an E_tree corresponding to the region tree (tp) */
00301 union E_tree *
00302 build_etree(union tree                  *tp,
00303             struct dg_client_data       *dgcdp)
00304 {
00305         union E_tree *eptr = NULL;
00306         struct soltab *stp;
00307         struct directory *dp;
00308 
00309         RT_CK_TREE( tp );
00310 
00311         switch( tp->tr_op )
00312         {
00313                 case OP_UNION:
00314                 case OP_SUBTRACT:
00315                 case OP_INTERSECT:
00316                         BU_GETUNION( eptr, E_tree );
00317                         eptr->magic = E_TREE_MAGIC;
00318                         eptr->n.op = tp->tr_op;
00319                         eptr->n.left = build_etree( tp->tr_b.tb_left, dgcdp );
00320                         eptr->n.right = build_etree( tp->tr_b.tb_right, dgcdp );
00321                         break;
00322                 case OP_SOLID:
00323                         stp = tp->tr_a.tu_stp;
00324                         eptr = add_solid( stp->st_dp, stp->st_matp, dgcdp );
00325                         eptr->l.op = tp->tr_op;
00326                         BU_LIST_INIT( &eptr->l.seghead );
00327                         break;
00328                 case OP_DB_LEAF:
00329                         if( (dp=db_lookup( dgcdp->dgop->dgo_wdbp->dbip, tp->tr_l.tl_name, LOOKUP_NOISY )) == DIR_NULL )
00330                         {
00331                                 eptr->l.m = (struct model *)NULL;
00332                                 break;
00333                         }
00334                         eptr = add_solid( dp, tp->tr_l.tl_mat, dgcdp );
00335                         eptr->l.op = tp->tr_op;
00336                         BU_LIST_INIT( &eptr->l.seghead );
00337                         break;
00338                 case OP_NOP:
00339                         /* add a NULL solid  */
00340                         BU_GETUNION( eptr, E_tree );
00341                         eptr->magic = E_TREE_MAGIC;
00342                         eptr->l.m = (struct model *)NULL;
00343                         break;
00344                 default:
00345                         bu_bomb("build_etree() Unknown tr_op\n");
00346         }
00347         return( eptr );
00348 }
00349 
00350 /* a handy routine (for debugging) that prints asegment list */
00351 void
00352 show_seg(struct bu_list *seg, int str)
00353 {
00354         struct seg *ptr;
00355 
00356         if( !seg )
00357                 bu_log( "%s - NULL seg list\n", str );
00358         else
00359         {
00360                 if( BU_LIST_IS_EMPTY( seg ) )
00361                         bu_log( "%s - empty\n", str );
00362                 else
00363                 {
00364                         bu_log( "%s:\n", str );
00365                         for( BU_LIST_FOR( ptr, seg, seg ) )
00366                         {
00367                                 if( ptr->seg_stp == ON_SURF )
00368                                         bu_log( "\t %g to %g (ON_SURF)\n", ptr->seg_in.hit_dist, ptr->seg_out.hit_dist );
00369                                 else if( ptr->seg_stp == ON_INT )
00370                                         bu_log( "\t %g to %g (ON_INT)\n", ptr->seg_in.hit_dist, ptr->seg_out.hit_dist );
00371                                 else if( ptr->seg_stp == IN_SOL )
00372                                         bu_log( "\t %g to %g (IN)\n", ptr->seg_in.hit_dist, ptr->seg_out.hit_dist );
00373                                 else
00374                                         bu_log( "\t %g to %g (?)\n", ptr->seg_in.hit_dist, ptr->seg_out.hit_dist );
00375                                 bu_log( "\t\t( %g %g %g) <-> (%g %g %g)\n", V3ARGS( ptr->seg_in.hit_point),
00376                                         V3ARGS( ptr->seg_out.hit_point ) );
00377                         }
00378                 }
00379         }
00380 }
00381 
00382 /* given a segment list, eliminate any overlaps in the segments */
00383 HIDDEN  void
00384 eliminate_overlaps(struct bu_list               *seghead,
00385                    struct dg_client_data        *dgcdp)
00386 {
00387         struct seg *a, *b, *nextb;
00388 
00389         a = BU_LIST_FIRST( seg, seghead );
00390         while( BU_LIST_NOT_HEAD( &a->l, seghead ) )
00391         {
00392                 b = BU_LIST_PNEXT( seg, &a->l );
00393                 if( BU_LIST_IS_HEAD( &b->l, seghead ) )
00394                         break;
00395 
00396                 while( BU_LIST_NOT_HEAD( &b->l, seghead ) )
00397                 {
00398                         nextb = BU_LIST_PNEXT( seg, &b->l );
00399                         if( NOT_SEG_OVERLAP( a, b ) )
00400                                 break;
00401 
00402                         if( b->seg_in.hit_dist < a->seg_out.hit_dist )
00403                         {
00404                                 if( b->seg_out.hit_dist > a->seg_out.hit_dist )
00405                                         a->seg_out.hit_dist = b->seg_out.hit_dist;
00406 
00407                                 BU_LIST_DEQUEUE( &b->l );
00408                                 RT_FREE_SEG( b, dgcdp->ap->a_resource );
00409                                 b = nextb;
00410                                 continue;
00411                         }
00412 
00413                         b = nextb;
00414                 }
00415 
00416                 a = BU_LIST_PNEXT(seg, &a->l );
00417         }
00418 }
00419 
00420 /* perform the intersection of two segments
00421  * the result is assigned the provided type
00422  */
00423 HIDDEN void
00424 do_intersect(struct seg                 *A,
00425              struct seg                 *B,
00426              struct bu_list             *seghead,
00427              struct soltab              *type,
00428              struct dg_client_data      *dgcdp)
00429 {
00430         struct seg *tmp=(struct seg *)NULL;
00431 
00432         if( NOT_SEG_OVERLAP( A, B ) )
00433                 return;
00434 
00435         RT_GET_SEG( tmp, dgcdp->ap->a_resource );
00436         if( A->seg_in.hit_dist <= B->seg_in.hit_dist )
00437         {
00438                 if( B->seg_out.hit_dist <= A->seg_out.hit_dist )
00439                 {
00440                         *tmp = *B;
00441                         tmp->seg_stp = type;
00442                 }
00443                 else
00444                 {
00445                         tmp->seg_in.hit_dist = B->seg_in.hit_dist;
00446                         tmp->seg_out.hit_dist = A->seg_out.hit_dist;
00447                         tmp->seg_stp = type;
00448                 }
00449         }
00450         else
00451         {
00452                 if( B->seg_out.hit_dist >= A->seg_out.hit_dist )
00453                 {
00454                         *tmp = *A;
00455                         tmp->seg_stp = type;
00456                 }
00457                 else
00458                 {
00459                         tmp->seg_in.hit_dist = A->seg_in.hit_dist;
00460                         tmp->seg_out.hit_dist = B->seg_out.hit_dist;
00461                         tmp->seg_stp = type;
00462                 }
00463         }
00464         if( tmp )
00465                 BU_LIST_INSERT( seghead, &tmp->l )
00466         return;
00467 }
00468 
00469 /* perform the subtraction of one segment from another
00470  * the result is assigned the type from segment A
00471  */
00472 HIDDEN void
00473 do_subtract(struct seg                  *A,
00474             struct seg                  *B,
00475             struct bu_list              *seghead,
00476             struct dg_client_data       *dgcdp)
00477 {
00478         struct seg *tmp=(struct seg *)NULL;
00479 
00480 
00481         if( NOT_SEG_OVERLAP( A, B ) )
00482         {
00483                 RT_GET_SEG( tmp, dgcdp->ap->a_resource )
00484                 *tmp = *A;
00485                 BU_LIST_INSERT( seghead, &tmp->l )
00486                 return;
00487         }
00488 
00489         if( B->seg_in.hit_dist<= A->seg_in.hit_dist )
00490         {
00491                 if( B->seg_out.hit_dist < A->seg_out.hit_dist )
00492                 {
00493                         RT_GET_SEG( tmp, dgcdp->ap->a_resource )
00494                         *tmp = *A;
00495                         tmp->seg_in.hit_dist = B->seg_out.hit_dist;
00496                         BU_LIST_INSERT( seghead, &tmp->l )
00497                         return;
00498                 }
00499                 else
00500                         return;
00501         }
00502         else
00503         {
00504                 if( B->seg_out.hit_dist >= A->seg_out.hit_dist )
00505                 {
00506                         RT_GET_SEG( tmp, dgcdp->ap->a_resource )
00507                         *tmp = *A;
00508                         tmp->seg_out.hit_dist = B->seg_in.hit_dist;
00509                         BU_LIST_INSERT( seghead, &tmp->l )
00510                         return;
00511                 }
00512                 else
00513                 {
00514                         RT_GET_SEG( tmp, dgcdp->ap->a_resource );
00515                         tmp->seg_in.hit_dist = A->seg_in.hit_dist;
00516                         tmp->seg_out.hit_dist = B->seg_in.hit_dist;
00517                         tmp->seg_stp = A->seg_stp;
00518                         BU_LIST_INSERT( seghead, &tmp->l )
00519                         RT_GET_SEG( tmp, dgcdp->ap->a_resource );
00520                         tmp->seg_in.hit_dist = B->seg_out.hit_dist;
00521                         tmp->seg_out.hit_dist = A->seg_out.hit_dist;
00522                         tmp->seg_stp = A->seg_stp;
00523                         BU_LIST_INSERT( seghead, &tmp->l )
00524                         return;
00525                 }
00526         }
00527 }
00528 
00529 /* perform the union of two segments
00530  * the types of A and B should be the same
00531  */
00532 HIDDEN void
00533 do_union(struct seg             *A,
00534          struct seg             *B,
00535          struct bu_list         *seghead,
00536          struct dg_client_data  *dgcdp)
00537 {
00538         struct seg *tmp;
00539 
00540         RT_GET_SEG( tmp, dgcdp->ap->a_resource )
00541 
00542         if( NOT_SEG_OVERLAP( A, B ) )
00543         {
00544                 if( A->seg_in.hit_dist <= B->seg_in.hit_dist )
00545                 {
00546                         *tmp = *A;
00547                         BU_LIST_INSERT( seghead, &tmp->l )
00548                         RT_GET_SEG( tmp, dgcdp->ap->a_resource )
00549                         *tmp = *B;
00550                         BU_LIST_INSERT( seghead, &tmp->l )
00551                 }
00552                 else
00553                 {
00554                         *tmp = *B;
00555                         BU_LIST_INSERT( seghead, &tmp->l )
00556                         RT_GET_SEG( tmp, dgcdp->ap->a_resource )
00557                         *tmp = *A;
00558                         BU_LIST_INSERT( seghead, &tmp->l )
00559                 }
00560                 return;
00561         }
00562 
00563         if( A->seg_in.hit_dist <= B->seg_in.hit_dist )
00564         {
00565                 *tmp = *A;
00566                 if( B->seg_out.hit_dist > A->seg_out.hit_dist )
00567                         tmp->seg_out.hit_dist = B->seg_out.hit_dist;
00568         }
00569         else
00570         {
00571                 *tmp = *B;
00572                 if( A->seg_out.hit_dist > B->seg_out.hit_dist )
00573                         tmp->seg_out.hit_dist = B->seg_out.hit_dist;
00574         }
00575 
00576         BU_LIST_INSERT( seghead, &tmp->l )
00577 }
00578 
00579 HIDDEN void
00580 promote_ints(struct bu_list             *head,
00581              struct dg_client_data      *dgcdp)
00582 {
00583         struct seg *a, *b, *tmp;
00584 
00585         #ifdef debug
00586         bu_log( "In promote_ints():\n" );
00587         show_seg( head, "SEGS" );
00588         for( BU_LIST_FOR( a, seg, head ) )
00589         {
00590                 b = BU_LIST_PNEXT( seg, &a->l );
00591                 if( BU_LIST_IS_HEAD( &b->l, head ) )
00592                         break;
00593 
00594                 if( b->seg_in.hit_dist < a->seg_in.hit_dist )
00595                         bu_log( "\tsegments out of order:\n" );
00596         }
00597         #endif
00598 
00599         a = BU_LIST_FIRST( seg, head );
00600         while( BU_LIST_NOT_HEAD( &a->l, head ) )
00601         {
00602                 b = BU_LIST_PNEXT( seg, &a->l );
00603                 while( BU_LIST_NOT_HEAD( &b->l, head ) )
00604                 {
00605                         if( a->seg_stp == ON_INT && b->seg_stp == ON_SURF )
00606                         {
00607                                 if( NOT_SEG_OVERLAP( a, b ) )
00608                                 {
00609                                         b = BU_LIST_PNEXT( seg, &b->l );
00610                                         continue;
00611                                 }
00612 
00613                                 if( a->seg_in.hit_dist == b->seg_in.hit_dist &&
00614                                     a->seg_out.hit_dist == b->seg_out.hit_dist )
00615                                 {
00616                                         a->seg_stp = ON_SURF;
00617                                         tmp = b;
00618                                         b = BU_LIST_PNEXT( seg, &b->l );
00619                                         BU_LIST_DEQUEUE( &tmp->l )
00620                                         RT_FREE_SEG( tmp, dgcdp->ap->a_resource )
00621                                         continue;;
00622                                 }
00623 
00624                                 if( a->seg_out.hit_dist == b->seg_out.hit_dist )
00625                                         a->seg_out.hit_dist = b->seg_in.hit_dist;
00626                                 else if( a->seg_out.hit_dist < b->seg_out.hit_dist )
00627                                 {
00628                                         if( b->seg_in.hit_dist > a->seg_in.hit_dist )
00629                                                 a->seg_out.hit_dist = b->seg_in.hit_dist;
00630                                         else
00631                                         {
00632                                                 tmp = a;
00633                                                 a  = BU_LIST_PLAST( seg, &a->l );
00634                                                 BU_LIST_DEQUEUE( &tmp->l )
00635                                                 RT_FREE_SEG( tmp, dgcdp->ap->a_resource )
00636                                                 break;
00637                                         }
00638                                 }
00639                                 else if( a->seg_in.hit_dist == b->seg_in.hit_dist )
00640                                 {
00641                                         fastf_t tmp_dist;
00642 
00643                                         tmp_dist = a->seg_out.hit_dist;
00644                                         a->seg_out.hit_dist = b->seg_out.hit_dist;
00645                                         b->seg_in.hit_dist = a->seg_out.hit_dist;
00646                                         b->seg_out.hit_dist = tmp_dist;
00647                                         a->seg_stp = ON_SURF;
00648                                         b->seg_stp = ON_INT;
00649                                 }
00650                                 else
00651                                 {
00652                                         RT_GET_SEG( tmp, dgcdp->ap->a_resource )
00653                                         *tmp = *a;
00654                                         tmp->seg_in.hit_dist = b->seg_out.hit_dist;
00655                                         a->seg_out.hit_dist = b->seg_in.hit_dist;
00656                                         BU_LIST_APPEND( &b->l, &tmp->l )
00657                                 }
00658                         }
00659                         else if( b->seg_stp == ON_INT && a->seg_stp == ON_SURF )
00660                         {
00661                                 if( NOT_SEG_OVERLAP( b, a ) )
00662                                 {
00663                                         b = BU_LIST_PNEXT( seg, &b->l );
00664                                         continue;
00665                                 }
00666 
00667                                 if( b->seg_in.hit_dist == a->seg_in.hit_dist &&
00668                                     b->seg_out.hit_dist == a->seg_out.hit_dist )
00669                                 {
00670                                         b->seg_stp = ON_SURF;
00671                                         tmp = a;
00672                                         a = BU_LIST_PLAST( seg, &a->l );
00673                                         BU_LIST_DEQUEUE( &tmp->l )
00674                                         RT_FREE_SEG( tmp, dgcdp->ap->a_resource )
00675                                         break;
00676                                 }
00677 
00678                                 if( b->seg_out.hit_dist == a->seg_out.hit_dist )
00679                                 {
00680                                         tmp = b;
00681                                         b = BU_LIST_PNEXT( seg, &b->l );
00682                                         BU_LIST_DEQUEUE( &tmp->l )
00683                                         RT_FREE_SEG( tmp, dgcdp->ap->a_resource )
00684                                 }
00685                                 else if( b->seg_out.hit_dist < a->seg_out.hit_dist )
00686                                 {
00687                                         if( a->seg_in.hit_dist > b->seg_in.hit_dist )
00688                                                 b->seg_out.hit_dist = a->seg_in.hit_dist;
00689                                         else
00690                                         {
00691                                                 tmp = b;
00692                                                 b = BU_LIST_PNEXT( seg, &b->l );
00693                                                 BU_LIST_DEQUEUE( &tmp->l )
00694                                                 RT_FREE_SEG( tmp, dgcdp->ap->a_resource )
00695                                                 continue;
00696                                         }
00697                                 }
00698                                 else if( b->seg_in.hit_dist == a->seg_in.hit_dist )
00699                                         b->seg_in.hit_dist = a->seg_out.hit_dist;
00700                                 else
00701                                 {
00702                                         RT_GET_SEG( tmp, dgcdp->ap->a_resource )
00703                                         *tmp = *b;
00704                                         tmp->seg_in.hit_dist = a->seg_out.hit_dist;
00705                                         b->seg_out.hit_dist = a->seg_in.hit_dist;
00706                                         BU_LIST_APPEND( &a->l, &tmp->l )
00707                                 }
00708                         }
00709 
00710                         if( (a->seg_stp != ON_INT) || (b->seg_stp != ON_INT) )
00711                         {
00712                                 b = BU_LIST_PNEXT( seg, &b->l );
00713                                 continue;
00714                         }
00715 
00716                         if( NOT_SEG_OVERLAP( a, b ) )
00717                         {
00718                                 b = BU_LIST_PNEXT( seg, &b->l );
00719                                 continue;
00720                         }
00721 
00722                         #ifdef debug
00723                         bu_log( "\tfound overlapping ON_INT segs:\n" );
00724                         #endif
00725 
00726                         if( a->seg_in.hit_dist == b->seg_in.hit_dist &&
00727                             a->seg_out.hit_dist == b->seg_out.hit_dist )
00728                         {
00729                                 #ifdef debug
00730                                 bu_log( "Promoting A, eliminating B\n" );
00731                                 #endif
00732 
00733                                 a->seg_stp = ON_SURF;
00734                                 BU_LIST_DEQUEUE( &b->l )
00735                                 RT_FREE_SEG( b, dgcdp->ap->a_resource )
00736                                 break;
00737                         }
00738 
00739                         if( a->seg_out.hit_dist == b->seg_out.hit_dist )
00740                         {
00741                                 b->seg_stp = ON_SURF;
00742                                 a->seg_out.hit_dist = b->seg_in.hit_dist;
00743 
00744                                 #ifdef debug
00745                                 bu_log( "Promoting B, reducing A:\n" );
00746                                 #endif
00747                         }
00748                         else if( a->seg_out.hit_dist < b->seg_out.hit_dist )
00749                         {
00750                                 if( b->seg_in.hit_dist > a->seg_in.hit_dist )
00751                                 {
00752                                         RT_GET_SEG( tmp, dgcdp->ap->a_resource )
00753                                         tmp->seg_stp = ON_SURF;
00754                                         tmp->seg_in.hit_dist = b->seg_in.hit_dist;
00755                                         tmp->seg_out.hit_dist = a->seg_out.hit_dist;
00756                                         b->seg_in.hit_dist = a->seg_out.hit_dist;
00757                                         a->seg_out.hit_dist = tmp->seg_in.hit_dist;
00758                                         BU_LIST_INSERT( &b->l, &tmp->l )
00759 
00760                                         #ifdef debug
00761                                         bu_log( "--==__ overlap\n" );
00762                                         #endif
00763                                 }
00764                                 else
00765                                 {
00766                                         b->seg_in.hit_dist = a->seg_out.hit_dist;
00767                                         a->seg_stp = ON_SURF;
00768 
00769                                         #ifdef debug
00770                                         bu_log( "A within B\n" );
00771                                         #endif
00772                                 }
00773                         }
00774                         else
00775                         {
00776                                 if( a->seg_in.hit_dist == b->seg_in.hit_dist )
00777                                 {
00778                                         fastf_t tmp_dist;
00779 
00780                                         tmp_dist = a->seg_out.hit_dist;
00781                                         a->seg_out.hit_dist = b->seg_out.hit_dist;
00782                                         a->seg_stp = ON_SURF;
00783                                         b->seg_in.hit_dist = a->seg_out.hit_dist;
00784                                         b->seg_out.hit_dist = tmp_dist;
00785                                 }
00786                                 else
00787                                 {
00788                                         RT_GET_SEG( tmp, dgcdp->ap->a_resource )
00789                                         *tmp = *a;
00790                                         tmp->seg_in.hit_dist = b->seg_out.hit_dist;
00791                                         a->seg_out.hit_dist = b->seg_in.hit_dist;
00792                                         b->seg_stp = ON_SURF;
00793                                         BU_LIST_APPEND( &b->l, &tmp->l )
00794 
00795                                         #ifdef debug
00796                                         bu_log( "B within A:\n" );
00797                                         #endif
00798                                 }
00799                         }
00800                         b = BU_LIST_PNEXT( seg, &b->l );
00801                 }
00802                 a = BU_LIST_PNEXT( seg, &a->l );
00803         }
00804 
00805         #ifdef debug
00806         bu_log( "Results of promote_ints()\n" );
00807         show_seg( head, "SEGS" );
00808         #endif
00809 }
00810 
00811 /* Evaluate an operation on the operands (segment lists) */
00812 HIDDEN struct bu_list *
00813 eval_op(struct bu_list          *A,
00814         int                     op,
00815         struct bu_list          *B,
00816         struct dg_client_data   *dgcdp)
00817 {
00818         struct seg *sega, *segb, *tmp, *next;
00819         struct bu_list ret, ons, ins;
00820         int inserted;
00821 
00822         BU_LIST_INIT( &ret );
00823 
00824         #ifdef debug
00825         bu_log( "In eval_op:\n" );
00826         show_seg( A, "\tA:" );
00827         show_seg( B, "\tB:" );
00828         #endif
00829 
00830         switch( op )
00831         {
00832                 case OP_SUBTRACT:
00833 
00834                         #ifdef debug
00835                         bu_log( "\t\tSUBTACT\n" );
00836                         #endif
00837 
00838                         if( BU_LIST_IS_EMPTY( A ) )
00839                         {
00840                                 MY_FREE_SEG_LIST( B, dgcdp->ap->a_resource );
00841                                 bu_free( (char *)B, "bu_list" );
00842 
00843                                 #ifdef debug
00844                                 show_seg( A, "Returning" );
00845                                 #endif
00846 
00847                                 return( A );
00848                         }
00849                         else if( BU_LIST_IS_EMPTY( B ) )
00850                         {
00851                                 bu_free( (char *)B, "bu_list" );
00852 
00853                                 #ifdef debug
00854                                 show_seg( A, "Returning" );
00855                                 #endif
00856 
00857                                 return( A );
00858                         }
00859 
00860                         /* A - B:
00861                          *      keep segments:
00862                          *                      ON_A - IN_B
00863                          *                      ON_A - ON_B
00864                          *                      ON_B + IN_A
00865                          *                      IN_A - IN_B
00866                          */
00867                         for( BU_LIST_FOR( sega, seg, A ) )
00868                         {
00869                                 for( BU_LIST_FOR( segb, seg, B ) )
00870                                 {
00871                                         if( sega->seg_stp == ON_INT && segb->seg_stp == ON_INT )
00872                                                 do_intersect( sega, segb, &ret, ON_SURF, dgcdp );
00873                                         else if( sega->seg_stp == ON_SURF || sega->seg_stp == ON_INT )
00874                                         {
00875                                                 do_subtract( sega, segb, &ret, dgcdp );
00876                                         }
00877                                         else if( segb->seg_stp == ON_SURF ||  segb->seg_stp == ON_INT )
00878                                                 do_intersect( segb, sega, &ret, segb->seg_stp, dgcdp );
00879                                 }
00880                         }
00881                         MY_FREE_SEG_LIST( B, dgcdp->ap->a_resource );
00882                         bu_free( (char *)B, "bu_list" );
00883                         MY_FREE_SEG_LIST( A, dgcdp->ap->a_resource );
00884                         BU_LIST_INSERT_LIST( A, &ret )
00885 
00886                         #ifdef debug
00887                         show_seg( A, "Returning" );
00888                         #endif
00889 
00890                         return( A );
00891                 case OP_INTERSECT:
00892 
00893                         #ifdef debug
00894                         bu_log( "\t\tINTERSECT\n" );
00895                         #endif
00896 
00897                         if( BU_LIST_IS_EMPTY( A ) || BU_LIST_IS_EMPTY( B ) )
00898                         {
00899                                 MY_FREE_SEG_LIST( A, dgcdp->ap->a_resource );
00900                                 MY_FREE_SEG_LIST( B, dgcdp->ap->a_resource );
00901                                 bu_free( (char *)B, "bu_list" );
00902 
00903                                 #ifdef debug
00904                                 show_seg( A, "Returning" );
00905                                 #endif
00906 
00907                                 return( A );
00908                         }
00909                         /* A + B
00910                          *      This is merely the intersection of segments from A with those from B
00911                          *      The two different calls to "do_intersect" get the types (IN, ON) right
00912                          */
00913                         for( BU_LIST_FOR( sega, seg, A ) )
00914                         {
00915                                 for( BU_LIST_FOR( segb, seg, B ) )
00916                                 {
00917                                         if( sega->seg_stp == ON_INT && segb->seg_stp == ON_INT )
00918                                                 do_intersect( sega, segb, &ret, ON_SURF, dgcdp );
00919                                         else if( sega->seg_stp == ON_SURF || sega->seg_stp == ON_INT )
00920                                                 do_intersect( sega, segb, &ret, sega->seg_stp, dgcdp );
00921                                         else
00922                                                 do_intersect( segb, sega, &ret, segb->seg_stp, dgcdp );
00923                                 }
00924                         }
00925                         MY_FREE_SEG_LIST( B, dgcdp->ap->a_resource );
00926                         bu_free( (char *)B, "bu_list" );
00927                         MY_FREE_SEG_LIST( A, dgcdp->ap->a_resource );
00928                         BU_LIST_INSERT_LIST( A, &ret )
00929 
00930                         #ifdef debug
00931                         show_seg( A, "Returning" );
00932                         #endif
00933 
00934                         return( A );
00935                 case OP_UNION:
00936 
00937                         #ifdef debug
00938                         bu_log( "\t\tUNION\n" );
00939                         #endif
00940 
00941                         if( BU_LIST_IS_EMPTY( A ) )
00942                         {
00943                                 bu_free( (char *)A, "bu_list" );
00944 
00945                                 #ifdef debug
00946                                 show_seg( B, "Returning B (A is empty)" );
00947                                 #endif
00948 
00949                                 return( B );
00950                         }
00951                         if( BU_LIST_IS_EMPTY( B ) )
00952                         {
00953                                 bu_free( (char *)B, "bu_list" );
00954 
00955                                 #ifdef debug
00956                                 show_seg( A, "Returning A (B is empty)" );
00957                                 #endif
00958 
00959                                 return( A );
00960                         }
00961                         /* A u B:
00962                          *      keep segments:
00963                          *              ON_A - IN_B (ON)
00964                          *              IN_B + ON_A (IN )
00965                          *              ON_B - IN_A (ON)
00966                          *              IN_A + ON_B (IN)
00967                          *              all remaining unique ON or IN segments
00968                          */
00969 
00970                         /* create two new lists, one with all the ON segments,
00971                          * the other with all the IN segments
00972                          */
00973                         BU_LIST_INIT( &ons )
00974                         BU_LIST_INIT( &ins )
00975 
00976                         /* Put the A operand segments on the lists */
00977                         while( BU_LIST_WHILE( sega, seg, A ) )
00978                         {
00979                                 BU_LIST_DEQUEUE( &sega->l )
00980 
00981                                 if( sega->seg_stp == ON_SURF || sega->seg_stp == ON_INT )
00982                                         BU_LIST_INSERT( &ons, &sega->l )
00983                                 else
00984                                         BU_LIST_INSERT( &ins, &sega->l )
00985                         }
00986 
00987                         /* insert the B operand segments in the lists (maintaining order from smaller starting
00988                          * hit distance to larger
00989                          */
00990                         while( BU_LIST_WHILE( segb, seg, B ) )
00991                         {
00992                                 int inserted;
00993                                 BU_LIST_DEQUEUE( &segb->l )
00994 
00995                                 if( segb->seg_stp == IN_SOL )
00996                                 {
00997                                         inserted = 0;
00998                                         for( BU_LIST_FOR( tmp, seg, &ins ) )
00999                                         {
01000                                                 if( tmp->seg_in.hit_dist >= segb->seg_in.hit_dist )
01001                                                 {
01002                                                         inserted = 1;
01003                                                         BU_LIST_INSERT( &tmp->l, &segb->l )
01004                                                         break;
01005                                                 }
01006                                         }
01007                                         if( !inserted )
01008                                                 BU_LIST_INSERT( &ins, &segb->l )
01009                                 }
01010                                 else
01011                                 {
01012                                         inserted = 0;
01013                                         for( BU_LIST_FOR( tmp, seg, &ons ) )
01014                                         {
01015                                                 if( tmp->seg_in.hit_dist >= segb->seg_in.hit_dist )
01016                                                 {
01017                                                         inserted = 1;
01018                                                         BU_LIST_INSERT( &tmp->l, &segb->l )
01019                                                         break;
01020                                                 }
01021                                         }
01022                                         if( !inserted )
01023                                                 BU_LIST_INSERT( &ons, &segb->l )
01024                                 }
01025                         }
01026 
01027                         /* promote intersecting ON_INT's to ON_SURF */
01028                         promote_ints( &ons, dgcdp );
01029 
01030                         /* make sure the segments are unique */
01031                         eliminate_overlaps( &ins, dgcdp );
01032                         eliminate_overlaps( &ons, dgcdp );
01033 
01034                         #ifdef debug
01035                         show_seg( &ons, "ONS" );
01036                         show_seg( &ins, "INS" );
01037                         #endif
01038 
01039                         /* subtract INS from ONS */
01040                         #ifdef debug
01041                         bu_log( "doing subtraction:\n" );
01042                         #endif
01043                         sega = BU_LIST_FIRST( seg, &ons );
01044                         while( BU_LIST_NOT_HEAD( &sega->l, &ons ) )
01045                         {
01046                                 next = BU_LIST_PNEXT( seg, &sega->l );
01047 
01048                                 #ifdef debug
01049                                 bu_log( "A is %g to %g:\n", sega->seg_in.hit_dist, sega->seg_out.hit_dist );
01050                                 #endif
01051 
01052                                 for( BU_LIST_FOR( segb, seg, &ins ) )
01053                                 {
01054                                         #ifdef debug
01055                                         bu_log( "\tcomparing to B %g to %g\n", segb->seg_in.hit_dist, segb->seg_out.hit_dist );
01056                                         #endif
01057 
01058                                         if( NOT_SEG_OVERLAP( sega, segb ) )
01059                                         {
01060                                                 #ifdef debug
01061                                                 bu_log( "\t\tNo overlap!!\n" );
01062                                                 #endif
01063 
01064                                                 continue;
01065                                         }
01066 
01067                                         if( segb->seg_in.hit_dist <= sega->seg_in.hit_dist &&
01068                                             segb->seg_out.hit_dist >= sega->seg_out.hit_dist )
01069                                         {
01070                                                 #ifdef debug
01071                                                 bu_log( "\t\teliminating A\n" );
01072                                                 #endif
01073 
01074                                                 /* eliminate sega */
01075                                                 BU_LIST_DEQUEUE( &sega->l )
01076                                                 RT_FREE_SEG( sega, dgcdp->ap->a_resource )
01077                                                 sega = next;
01078                                                 break;
01079                                         }
01080 
01081                                         if( segb->seg_in.hit_dist > sega->seg_in.hit_dist &&
01082                                             segb->seg_out.hit_dist < sega->seg_out.hit_dist )
01083                                         {
01084                                                 /* split sega */
01085                                                 RT_GET_SEG( tmp, dgcdp->ap->a_resource )
01086                                                 *tmp = *sega;
01087                                                 tmp->seg_in.hit_dist = segb->seg_out.hit_dist;
01088                                                 sega->seg_out.hit_dist = segb->seg_in.hit_dist;
01089                                                 BU_LIST_APPEND( &sega->l, &tmp->l )
01090                                                 next = tmp;
01091 
01092                                                 #ifdef debug
01093                                                 bu_log( "\t\tsplit A into: %g to %g and %g to %g\n", sega->seg_in.hit_dist, sega->seg_out.hit_dist, tmp->seg_in.hit_dist, tmp->seg_out.hit_dist );
01094                                                 #endif
01095                                         }
01096                                         else
01097                                         {
01098                                                 /* subtract edges */
01099                                                 if( segb->seg_in.hit_dist > sega->seg_in.hit_dist )
01100                                                         sega->seg_out.hit_dist = segb->seg_in.hit_dist;
01101                                                 if( segb->seg_out.hit_dist < sega->seg_out.hit_dist )
01102                                                         sega->seg_in.hit_dist = segb->seg_out.hit_dist;
01103 
01104                                                 #ifdef debug
01105                                                 bu_log( "\t\tsubtracted A down to %g to %g\n", sega->seg_in.hit_dist, sega->seg_out.hit_dist );
01106                                                 #endif
01107                                         }
01108                                 }
01109                                 sega = next;
01110                         }
01111 
01112                         /* put the resuling ONS list on the result list */
01113                         BU_LIST_INSERT_LIST( &ret, &ons )
01114 
01115                         /* add INS to the return list (maintain order) */
01116                         while( BU_LIST_WHILE( sega, seg, &ins ) )
01117                         {
01118                                 BU_LIST_DEQUEUE( &sega->l )
01119 
01120                                 inserted = 0;
01121                                 for( BU_LIST_FOR( segb, seg, &ret ) )
01122                                 {
01123                                         if( sega->seg_in.hit_dist < segb->seg_in.hit_dist )
01124                                         {
01125                                                 BU_LIST_INSERT( &segb->l, &sega->l )
01126                                                 inserted = 1;
01127                                                 break;
01128                                         }
01129                                 }
01130 
01131                                 if( !inserted )
01132                                         BU_LIST_INSERT( &ret, &sega->l )
01133                         }
01134 
01135                         MY_FREE_SEG_LIST( B, dgcdp->ap->a_resource );
01136                         bu_free( (char *)B, "bu_list" );
01137                         MY_FREE_SEG_LIST( A, dgcdp->ap->a_resource );
01138                         BU_LIST_INSERT_LIST( A, &ret )
01139 
01140                         #ifdef debug
01141                         show_seg( A, "Returning" );
01142                         #endif
01143 
01144                         return( A );
01145         }
01146 
01147         /* should never get here */
01148         MY_FREE_SEG_LIST( A, dgcdp->ap->a_resource );
01149         MY_FREE_SEG_LIST( B, dgcdp->ap->a_resource );
01150         bu_free( (char *)B, "bu_list" );
01151 
01152         #ifdef debug
01153         show_seg( A, "Returning (default)" );
01154         #endif
01155 
01156         return( A );
01157 
01158 }
01159 
01160 /* evaluate an E-tree */
01161 HIDDEN struct bu_list *
01162 eval_etree(union E_tree                 *eptr,
01163            struct dg_client_data        *dgcdp)
01164 
01165 {
01166         struct bu_list *A, *B;
01167 
01168         CK_ETREE( eptr );
01169 
01170         #ifdef debug
01171         bu_log( "In eval_etree:\n" );
01172         #endif
01173 
01174         switch( eptr->l.op )
01175         {
01176                 case OP_DB_LEAF:
01177                 case OP_SOLID:
01178                         A = (struct bu_list *)bu_malloc( sizeof( struct bu_list ), "bu_list" );
01179                         BU_LIST_INIT( A );
01180                         BU_LIST_INSERT_LIST( A, &eptr->l.seghead )
01181 
01182                         #ifdef debug
01183                         show_seg( A, "LEAF:" );
01184                         #endif
01185 
01186                         return( A );
01187                 case OP_SUBTRACT:
01188                 case OP_INTERSECT:
01189                 case OP_UNION:
01190                         #ifdef debug
01191                         bu_log( "Evaluating subtrees\n" );
01192                         #endif
01193 
01194                         A = eval_etree( eptr->n.left, dgcdp );
01195                         B = eval_etree( eptr->n.right, dgcdp );
01196                         return( eval_op( A, eptr->n.op, B, dgcdp ) );
01197         }
01198 
01199         /* should never get here */
01200         return( (struct bu_list *)NULL );       /* for the compilers */
01201 }
01202 
01203 HIDDEN void
01204 inverse_dir( vect_t dir, vect_t inv_dir )
01205 {
01206         /* Compute the inverse of the direction cosines */
01207         if( !NEAR_ZERO( dir[X], SQRT_SMALL_FASTF ) )  {
01208                 inv_dir[X]=1.0/dir[X];
01209         } else {
01210                 inv_dir[X] = INFINITY;
01211                 dir[X] = 0.0;
01212         }
01213         if( !NEAR_ZERO( dir[Y], SQRT_SMALL_FASTF ) )  {
01214                 inv_dir[Y]=1.0/dir[Y];
01215         } else {
01216                 inv_dir[Y] = INFINITY;
01217                 dir[Y] = 0.0;
01218         }
01219         if( !NEAR_ZERO( dir[Z], SQRT_SMALL_FASTF ) )  {
01220                 inv_dir[Z]=1.0/dir[Z];
01221         } else {
01222                 inv_dir[Z] = INFINITY;
01223                 dir[Z] = 0.0;
01224         }
01225 }
01226 
01227 HIDDEN struct soltab *
01228 classify_seg( struct seg *seg, struct soltab *shoot, struct xray *rp, struct dg_client_data *dgcdp )
01229 {
01230         fastf_t mid_dist;
01231         struct xray new_rp;
01232         struct ray_data rd;
01233         struct soltab *ret = IN_SOL;
01234 
01235         bzero( &rd, sizeof( struct ray_data ) );
01236 
01237         BU_GETSTRUCT( rd.seghead, seg );
01238         BU_LIST_INIT( &rd.seghead->l );
01239 
01240         mid_dist = (seg->seg_in.hit_dist + seg->seg_out.hit_dist) / 2.0;
01241         VJOIN1( new_rp.r_pt, rp->r_pt, mid_dist, rp->r_dir );
01242 #ifdef debug
01243         bu_log( "Classifying segment with mid_pt (%g %g %g) with respct to %s\n", V3ARGS( new_rp.r_pt ), shoot->st_dp->d_namep );
01244 #endif
01245 
01246         bn_vec_ortho( new_rp.r_dir, rp->r_dir );
01247         inverse_dir( new_rp.r_dir, rd.rd_invdir );
01248 
01249         /* set up "ray_data" structure for nmg raytrace */
01250         rd.rp = &new_rp;
01251         rd.tol = &dgcdp->dgop->dgo_wdbp->wdb_tol;
01252         rd.ap = dgcdp->ap;
01253         rd.magic = NMG_RAY_DATA_MAGIC;
01254         rd.classifying_ray = 0;
01255         rd.hitmiss = (struct hitmiss **)NULL;
01256         rd.stp = shoot;
01257 
01258         if( rt_functab[shoot->st_id].ft_shot( shoot, &new_rp, dgcdp->ap, rd.seghead ) ) {
01259                 struct seg *seg;
01260 
01261                 while( BU_LIST_WHILE( seg, seg, &rd.seghead->l ) ) {
01262                         BU_LIST_DEQUEUE( &seg->l );
01263 #ifdef debug
01264                         bu_log( "dist = %g and %g\n", seg->seg_in.hit_dist,
01265                                 seg->seg_out.hit_dist );
01266 #endif
01267                         if( ret != ON_SURF ) {
01268                                 if( NEAR_ZERO( seg->seg_in.hit_dist, rd.tol->dist ) ) {
01269                                         ret = ON_SURF;
01270                                 }
01271                                 if( NEAR_ZERO( seg->seg_out.hit_dist, rd.tol->dist ) ) {
01272                                         ret = ON_SURF;
01273                                 }
01274                         }
01275                         RT_FREE_SEG( seg, dgcdp->ap->a_resource );
01276                 }
01277         }
01278 
01279         if( ret != ON_SURF ) {
01280                 vect_t new_dir;
01281 
01282                 VCROSS( new_dir, new_rp.r_dir, rp->r_dir );
01283                 VMOVE( new_rp.r_dir, new_dir );
01284                 inverse_dir( new_rp.r_dir, rd.rd_invdir );
01285                 if( rt_functab[shoot->st_id].ft_shot( shoot, &new_rp, dgcdp->ap, rd.seghead ) ) {
01286                         struct seg *seg;
01287 
01288                         while( BU_LIST_WHILE( seg, seg, &rd.seghead->l ) ) {
01289                                 BU_LIST_DEQUEUE( &seg->l );
01290 #ifdef debug
01291                                 bu_log( "dist = %g and %g\n", seg->seg_in.hit_dist,
01292                                         seg->seg_out.hit_dist );
01293 #endif
01294                                 if( ret != ON_SURF ) {
01295                                         if( NEAR_ZERO( seg->seg_in.hit_dist, rd.tol->dist ) ) {
01296                                                 ret = ON_SURF;
01297                                         }
01298                                         if( NEAR_ZERO( seg->seg_out.hit_dist, rd.tol->dist ) ) {
01299                                                 ret = ON_SURF;
01300                                         }
01301                                 }
01302                                 RT_FREE_SEG( seg, dgcdp->ap->a_resource );
01303                         }
01304                 }
01305         }
01306 #ifdef debug
01307         bu_log( "\t x%x\n", ret );
01308 #endif
01309         return ret;
01310 }
01311 
01312 /* Shoot rays (corresponding to possible edges in the result)
01313  * at the solids, put the results in the E-tree leaves as type IN_SOL.
01314  * Call eval_etree() and plot the results
01315  */
01316 HIDDEN void
01317 shoot_and_plot(point_t                  start_pt,
01318                vect_t                   dir,
01319                struct bu_list           *vhead,
01320                fastf_t                  edge_len,
01321                int                      skip_leaf1,
01322                int                      skip_leaf2,
01323                union E_tree             *eptr,
01324                struct soltab            *type,
01325                struct dg_client_data    *dgcdp)
01326 {
01327         struct xray rp;
01328         struct ray_data rd;
01329         int shoot_leaf;
01330         struct bu_list *final_segs;
01331 
01332         if( bu_debug&BU_DEBUG_MEM_CHECK && bu_mem_barriercheck() )
01333                 bu_log( "Error at start of shoot_and_plot()\n" );
01334 
01335         CK_ETREE( eptr );
01336 
01337         bzero( &rd, sizeof( struct ray_data ) );
01338 
01339         BU_GETSTRUCT( rd.seghead, seg );
01340         BU_LIST_INIT( &rd.seghead->l );
01341 
01342         VMOVE( rp.r_pt, start_pt )
01343         VMOVE( rp.r_dir, dir )
01344         /* Compute the inverse of the direction cosines */
01345         if( !NEAR_ZERO( rp.r_dir[X], SQRT_SMALL_FASTF ) )  {
01346                 rd.rd_invdir[X]=1.0/rp.r_dir[X];
01347         } else {
01348                 rd.rd_invdir[X] = INFINITY;
01349                 rp.r_dir[X] = 0.0;
01350         }
01351         if( !NEAR_ZERO( rp.r_dir[Y], SQRT_SMALL_FASTF ) )  {
01352                 rd.rd_invdir[Y]=1.0/rp.r_dir[Y];
01353         } else {
01354                 rd.rd_invdir[Y] = INFINITY;
01355                 rp.r_dir[Y] = 0.0;
01356         }
01357         if( !NEAR_ZERO( rp.r_dir[Z], SQRT_SMALL_FASTF ) )  {
01358                 rd.rd_invdir[Z]=1.0/rp.r_dir[Z];
01359         } else {
01360                 rd.rd_invdir[Z] = INFINITY;
01361                 rp.r_dir[Z] = 0.0;
01362         }
01363 
01364         /* set up "ray_data" structure for nmg raytrace */
01365         rd.rp = &rp;
01366         rd.tol = &dgcdp->dgop->dgo_wdbp->wdb_tol;
01367         rd.ap = dgcdp->ap;
01368         rd.magic = NMG_RAY_DATA_MAGIC;
01369         rd.classifying_ray = 0;
01370         rd.hitmiss = (struct hitmiss **)NULL;
01371 
01372         /* shoot this ray at every leaf solid except the one this edge came from
01373          * (or the two that this intersection line came from
01374          */
01375         for( shoot_leaf=0 ; shoot_leaf < BU_PTBL_END( &dgcdp->leaf_list ) ; shoot_leaf++ )
01376         {
01377                 union E_tree *shoot;
01378                 int dont_shoot=0;
01379 
01380                 shoot = (union E_tree *)BU_PTBL_GET( &dgcdp->leaf_list, shoot_leaf );
01381 
01382                 if( BU_LIST_NON_EMPTY( &shoot->l.seghead ) )
01383                 {
01384                         MY_FREE_SEG_LIST( &shoot->l.seghead, dgcdp->ap->a_resource );
01385                 }
01386                 BU_LIST_INIT( &shoot->l.seghead );
01387 
01388                 /* don't shoot rays at the leaves that were the source of this possible edge */
01389                 if( shoot_leaf == skip_leaf1 || shoot_leaf == skip_leaf2 )
01390                         dont_shoot = 1;
01391                 else
01392                 {
01393                         /* don't shoot at duplicate solids either */
01394                         union E_tree *leaf;
01395 
01396                         if( skip_leaf1 >= 0 )
01397                         {
01398                                 leaf = (union E_tree *)BU_PTBL_GET( &dgcdp->leaf_list, skip_leaf1 );
01399                                 if( leaf->l.stp->st_dp == shoot->l.stp->st_dp )
01400                                 {
01401                                         if( !leaf->l.stp->st_matp && !shoot->l.stp->st_matp )
01402                                                 dont_shoot = 1;
01403                                         else if( !leaf->l.stp->st_matp &&
01404                                                  bn_mat_is_equal( shoot->l.stp->st_matp,
01405                                                                   bn_mat_identity,
01406                                                                   &dgcdp->dgop->dgo_wdbp->wdb_tol ) )
01407                                                 dont_shoot = 1;
01408                                         else if( !shoot->l.stp->st_matp &&
01409                                                  bn_mat_is_equal( leaf->l.stp->st_matp,
01410                                                                   bn_mat_identity,
01411                                                                   &dgcdp->dgop->dgo_wdbp->wdb_tol ) )
01412                                                 dont_shoot = 1;
01413                                         else if( leaf->l.stp->st_matp &&
01414                                                  shoot->l.stp->st_matp &&
01415                                                  bn_mat_is_equal( leaf->l.stp->st_matp,
01416                                                                   shoot->l.stp->st_matp,
01417                                                                   &dgcdp->dgop->dgo_wdbp->wdb_tol ) )
01418                                                 dont_shoot = 1;
01419                                 }
01420                         }
01421                         if( !dont_shoot && skip_leaf2 >= 0 )
01422                         {
01423                                 leaf = (union E_tree *)BU_PTBL_GET( &dgcdp->leaf_list, skip_leaf2 );
01424                                 if( leaf->l.stp->st_dp == shoot->l.stp->st_dp )
01425                                 {
01426                                         if( !leaf->l.stp->st_matp && !shoot->l.stp->st_matp )
01427                                                 dont_shoot = 1;
01428                                         else if( !leaf->l.stp->st_matp &&
01429                                                  bn_mat_is_equal( shoot->l.stp->st_matp,
01430                                                                   bn_mat_identity,
01431                                                                   &dgcdp->dgop->dgo_wdbp->wdb_tol ) )
01432                                                 dont_shoot = 1;
01433                                         else if( !shoot->l.stp->st_matp &&
01434                                                  bn_mat_is_equal( leaf->l.stp->st_matp,
01435                                                                   bn_mat_identity,
01436                                                                   &dgcdp->dgop->dgo_wdbp->wdb_tol ) )
01437                                                 dont_shoot = 1;
01438                                         else if( leaf->l.stp->st_matp &&
01439                                                  shoot->l.stp->st_matp &&
01440                                                  bn_mat_is_equal( leaf->l.stp->st_matp,
01441                                                                   shoot->l.stp->st_matp,
01442                                                                   &dgcdp->dgop->dgo_wdbp->wdb_tol ) )
01443                                                 dont_shoot = 1;
01444                                 }
01445                         }
01446                 }
01447 
01448                 if( dont_shoot )
01449                 {
01450                         struct seg *seg;
01451 
01452                         /* put entire edge in seg list and mark it as ON the surface */
01453                         RT_GET_SEG( seg, dgcdp->ap->a_resource );
01454                         seg->l.magic = RT_SEG_MAGIC;
01455                         seg->seg_in.hit_dist = 0.0;
01456                         seg->seg_out.hit_dist = edge_len;
01457                         seg->seg_stp = type;
01458                         BU_LIST_INSERT( &shoot->l.seghead, &seg->l );
01459                         continue;
01460                 }
01461 
01462                 /* initialize the lists of things that have been hit/missed */
01463                 rd.rd_m = shoot->l.m;
01464                 BU_LIST_INIT(&rd.rd_hit);
01465                 BU_LIST_INIT(&rd.rd_miss);
01466 
01467                 rd.stp = shoot->l.stp;
01468 
01469                 /* actually shoot the ray, assign segments to the leaf, and mark them as IN_SOL */
01470                 if( rt_in_rpp( &rp, rd.rd_invdir, shoot->l.stp->st_min, shoot->l.stp->st_max ) )
01471                 {
01472                         if( rt_functab[shoot->l.stp->st_id].ft_shot( shoot->l.stp, &rp, dgcdp->ap, rd.seghead ) )
01473                         {
01474                                 struct seg *seg;
01475 
01476                                 /* put the segments in the lead solid structure */
01477                                 while( BU_LIST_WHILE( seg, seg, &rd.seghead->l ) )
01478                                 {
01479                                         BU_LIST_DEQUEUE( &seg->l )
01480                                         /* clip segments to the edge being considered */
01481                                         if( seg->seg_in.hit_dist >= edge_len || seg->seg_out.hit_dist <= 0 )
01482                                                 RT_FREE_SEG( seg, dgcdp->ap->a_resource )
01483                                         else
01484                                         {
01485                                                 if( seg->seg_in.hit_dist < 0.0 )
01486                                                         seg->seg_in.hit_dist = 0.0;
01487                                                 if( seg->seg_out.hit_dist > edge_len )
01488                                                         seg->seg_out.hit_dist = edge_len;
01489                                                 seg->seg_stp = classify_seg( seg, shoot->l.stp, &rp, dgcdp );
01490                                                 BU_LIST_INSERT(  &shoot->l.seghead, &seg->l )
01491                                         }
01492                                 }
01493                         }
01494                 }
01495         }
01496 
01497         /* Evaluate the Boolean tree to get the "final" segments
01498          * which are to be plotted.
01499          */
01500         #ifdef debug
01501         bu_log( "EVALUATING ETREE:\n" );
01502         bu_log( "ray start (%g %g %g), dir=(%g %g %g)\n", V3ARGS( start_pt ), V3ARGS( dir ) );
01503         #endif
01504 
01505         final_segs = eval_etree( eptr, dgcdp );
01506 
01507         #ifdef debug
01508         show_seg( final_segs, "DRAWING" );
01509         #endif
01510 
01511         if( final_segs )
01512         {
01513                 struct seg *seg;
01514 
01515                 /* add the segemnts to the VLIST */
01516                 for( BU_LIST_FOR( seg, seg, final_segs ) )
01517                 {
01518                         point_t pt;
01519 
01520                         /* only plot the resulting segments that are ON the SURFace */
01521                         if( seg->seg_stp != ON_SURF )
01522                                 continue;
01523 
01524                         dgcdp->nvectors++;
01525                         VJOIN1( pt, rp.r_pt, seg->seg_in.hit_dist, rp.r_dir )
01526 
01527                         #ifdef debug
01528                         bu_log( "\t\tDRAW (%g %g %g)", V3ARGS( pt ) );
01529                         #endif
01530 
01531                         RT_ADD_VLIST( vhead, pt, RT_VLIST_LINE_MOVE );
01532                         VJOIN1( pt, rp.r_pt, seg->seg_out.hit_dist, rp.r_dir )
01533 
01534                         #ifdef debug
01535                         bu_log( "<->(%g %g %g)\n", V3ARGS( pt ) );
01536                         #endif
01537 
01538                         RT_ADD_VLIST( vhead, pt, RT_VLIST_LINE_DRAW );
01539                 }
01540 
01541         }
01542 
01543         if( final_segs )
01544                 MY_FREE_SEG_LIST( final_segs, dgcdp->ap->a_resource );
01545         bu_free( (char *)final_segs, "bu_list" );
01546 
01547         if( bu_debug&BU_DEBUG_MEM_CHECK && bu_mem_barriercheck() )
01548                 bu_log( "Error at end of shoot_and_plot()\n" );
01549 
01550 }
01551 
01552 #define HITS_BLOCK      20
01553 
01554 HIDDEN void
01555 Eplot(union E_tree              *eptr,
01556       struct bu_list            *vhead,
01557       struct dg_client_data     *dgcdp)
01558 {
01559         point_t start_pt;
01560         int leaf_no;
01561         union E_tree *leaf_ptr;
01562         int hit_count1=0, hit_count2=0;
01563         point_t *hits1=NULL, *hits2=NULL;
01564         int hits_avail1=0, hits_avail2=0;
01565         int i;
01566         struct bu_list *result;
01567         struct bn_tol *tol;
01568 
01569         tol = &dgcdp->dgop->dgo_wdbp->wdb_tol;
01570 
01571         CK_ETREE( eptr );
01572 
01573         /* create an edge list for each leaf solid */
01574         for( leaf_no=0 ; leaf_no < BU_PTBL_END( &dgcdp->leaf_list ) ; leaf_no++ )
01575         {
01576                 leaf_ptr = (union E_tree *)BU_PTBL_GET( &dgcdp->leaf_list, leaf_no );
01577                 CK_ETREE( leaf_ptr );
01578                 if( leaf_ptr->l.op != OP_DB_LEAF && leaf_ptr->l.op != OP_SOLID )
01579                 {
01580                         Tcl_AppendResult(dgcdp->interp, "Eplot: Bad leaf node!!!\n", (char *)NULL );
01581                         return;
01582                 }
01583 
01584                 if( leaf_ptr->l.m )
01585                         nmg_edge_tabulate( &leaf_ptr->l.edge_list, &leaf_ptr->l.m->magic );
01586                 else
01587                         bu_ptbl_init( &leaf_ptr->l.edge_list, 1, "edge_list" );
01588         }
01589 
01590         /* now plot appropriate parts of each solid */
01591 
01592         /* loop through every leaf solid */
01593         for( leaf_no=0 ; leaf_no < BU_PTBL_END( &dgcdp->leaf_list ) ; leaf_no++ )
01594         {
01595                 int edge_no;
01596 
01597                 leaf_ptr = (union E_tree *)BU_PTBL_GET( &dgcdp->leaf_list, leaf_no );
01598 
01599                 if( !leaf_ptr->l.m )
01600                         continue;
01601 
01602                 /* do each edge of the current leaf solid */
01603                 for( edge_no=0 ; edge_no < BU_PTBL_END( &leaf_ptr->l.edge_list ) ; edge_no++ )
01604                 {
01605                         struct edge *e;
01606                         struct vertex_g *vg;
01607                         struct vertex_g *vg2;
01608                         vect_t dir;
01609                         fastf_t edge_len;
01610                         fastf_t inv_len;
01611 
01612                         e = (struct edge *)BU_PTBL_GET( &leaf_ptr->l.edge_list, edge_no );
01613                         NMG_CK_EDGE( e );
01614                         vg = e->eu_p->vu_p->v_p->vg_p;
01615                         NMG_CK_VERTEX_G( vg );
01616 
01617                         vg2 = e->eu_p->eumate_p->vu_p->v_p->vg_p;
01618                         NMG_CK_VERTEX_G( vg2 );
01619 
01620                         /* set up a ray from vg towards vg2 */
01621                         VSUB2( dir, vg2->coord, vg->coord );
01622                         edge_len = MAGNITUDE( dir );
01623                         if( edge_len < tol->dist )
01624                                 continue;
01625                         inv_len = 1.0/edge_len;
01626                         VSCALE( dir, dir, inv_len );
01627                         shoot_and_plot( vg->coord, dir, vhead, edge_len, leaf_no, -1, eptr, ON_SURF, dgcdp );
01628 
01629                 }
01630         }
01631 
01632         hits1 = (point_t *)bu_calloc( HITS_BLOCK, sizeof( point_t ), "hits" );
01633         hits_avail1 = HITS_BLOCK;
01634         hits2 = (point_t *)bu_calloc( HITS_BLOCK, sizeof( point_t ), "hits" );
01635         hits_avail2 = HITS_BLOCK;
01636 
01637         /* Now draw solid intersection lines */
01638         for( leaf_no=0 ; leaf_no < BU_PTBL_END( &dgcdp->leaf_list ) ; leaf_no++ )
01639         {
01640                 int leaf2;
01641 
01642                 leaf_ptr = (union E_tree *)BU_PTBL_GET( &dgcdp->leaf_list, leaf_no );
01643                 if( !leaf_ptr->l.m )
01644                         continue;
01645 
01646                 for( leaf2=leaf_no+1 ; leaf2 < BU_PTBL_END( &dgcdp->leaf_list ) ; leaf2++ )
01647                 {
01648                         union E_tree *leaf2_ptr;
01649                         struct nmgregion *r1, *r2;
01650                         struct shell *s1, *s2;
01651                         struct faceuse *fu1, *fu2;
01652                         struct face *f1, *f2;
01653                         plane_t pl1, pl2;
01654                         struct loopuse *lu1, *lu2;
01655                         struct edgeuse *eu1, *eu2;
01656                         struct vertex_g *vg1a, *vg1b, *vg2a, *vg2b;
01657                         struct bu_list *A, *B;
01658 
01659                         leaf2_ptr = (union E_tree *)BU_PTBL_GET( &dgcdp->leaf_list, leaf2 );
01660                         if( !leaf2_ptr->l.m )
01661                                 continue;
01662 
01663                         /* find intersection lines between these two NMG's */
01664 
01665                         r1 = BU_LIST_FIRST( nmgregion, &leaf_ptr->l.m->r_hd );
01666                         s1 = BU_LIST_FIRST( shell, &r1->s_hd );
01667                         r2 = BU_LIST_FIRST( nmgregion, &leaf2_ptr->l.m->r_hd );
01668                         s2 = BU_LIST_FIRST( shell, &r2->s_hd );
01669 
01670                         for( BU_LIST_FOR( fu1, faceuse, &s1->fu_hd ) )
01671                         {
01672                                 if( fu1->orientation != OT_SAME )
01673                                         continue;
01674 
01675                                 f1 = fu1->f_p;
01676                                 NMG_GET_FU_PLANE( pl1, fu1 );
01677 
01678                                 for( BU_LIST_FOR( fu2, faceuse, &s2->fu_hd ) )
01679                                 {
01680                                         fastf_t dist;
01681                                         vect_t dir;
01682                                         vect_t diff;
01683                                         fastf_t *dists1, *dists2;
01684                                         fastf_t min_dist, max_dist;
01685                                         int     min_hit, max_hit;
01686                                         int done;
01687                                         struct seg *aseg;
01688 
01689                                         if( fu2->orientation != OT_SAME )
01690                                                 continue;
01691 
01692                                         f2 = fu2->f_p;
01693 
01694                                         if ( !V3RPP_OVERLAP_TOL(f2->min_pt, f2->max_pt,
01695                                                                 f1->min_pt, f1->max_pt,
01696                                                                 tol) )
01697                                                         continue;
01698 
01699                                         NMG_GET_FU_PLANE( pl2, fu2 );
01700 
01701                                         if( bn_coplanar( pl1, pl2, tol ) ) {
01702                                                 continue;
01703                                         }
01704 
01705                                         hit_count1=0;
01706                                         hit_count2=0;
01707                                         for( BU_LIST_FOR( lu1, loopuse, &fu1->lu_hd ) )
01708                                         {
01709                                                 if( BU_LIST_FIRST_MAGIC( &lu1->down_hd ) != NMG_EDGEUSE_MAGIC )
01710                                                         continue;
01711 
01712                                                 for( BU_LIST_FOR( eu1, edgeuse, &lu1->down_hd ) )
01713                                                 {
01714                                                         vg1a = eu1->vu_p->v_p->vg_p;
01715                                                         vg1b = eu1->eumate_p->vu_p->v_p->vg_p;
01716                                                         VSUB2( dir, vg1b->coord, vg1a->coord );
01717 
01718                                                         /* find intersection of this edge with fu2 */
01719 
01720                                                         if( bn_isect_line3_plane( &dist, vg1a->coord,
01721                                                                                   dir, pl2,
01722                                                                                   tol ) < 1 )
01723                                                                 continue;
01724 
01725                                                         if( dist < -tol->dist || dist > 1.0 + tol->dist )
01726                                                                 continue;
01727 
01728                                                         if( hit_count1 >= hits_avail1 ) {
01729                                                                 hits_avail1 += HITS_BLOCK;
01730                                                                 hits1 = (point_t *)bu_realloc( hits1,
01731                                                                          hits_avail1 * sizeof( point_t ), "hits1" );
01732                                                         }
01733                                                         VJOIN1( hits1[hit_count1], vg1a->coord, dist, dir );
01734                                                         hit_count1++;
01735                                                 }
01736                                         }
01737                                         for( BU_LIST_FOR( lu2, loopuse, &fu2->lu_hd ) )
01738                                         {
01739                                                 if( BU_LIST_FIRST_MAGIC( &lu2->down_hd ) != NMG_EDGEUSE_MAGIC )
01740                                                         continue;
01741 
01742                                                 for( BU_LIST_FOR( eu2, edgeuse, &lu2->down_hd ) )
01743                                                 {
01744                                                         vg2a = eu2->vu_p->v_p->vg_p;
01745                                                         vg2b = eu2->eumate_p->vu_p->v_p->vg_p;
01746                                                         VSUB2( dir, vg2b->coord, vg2a->coord );
01747 
01748                                                         /* find intersection of this edge with fu1 */
01749 
01750                                                         if( bn_isect_line3_plane( &dist, vg2a->coord,
01751                                                                                   dir, pl1,
01752                                                                                   tol ) < 1 )
01753                                                                 continue;
01754 
01755                                                         if( dist < -tol->dist || dist > 1.0 + tol->dist )
01756                                                                 continue;
01757 
01758                                                         if( hit_count2 >= hits_avail2 ) {
01759                                                                 hits_avail2 += HITS_BLOCK;
01760                                                                 hits2 = (point_t *)bu_realloc( hits2,
01761                                                                          hits_avail2 * sizeof( point_t ), "hits2" );
01762                                                         }
01763                                                         VJOIN1( hits2[hit_count2], vg2a->coord, dist, dir );
01764                                                         hit_count2++;
01765                                                 }
01766                                         }
01767 
01768                                         if( hit_count1 < 2 || hit_count2 < 2 ) {
01769                                                 /* nothing to plot */
01770                                                 continue;
01771                                         }
01772 
01773                                         /* sort the hits on face 1 */
01774                                         dists1 = (fastf_t *)bu_calloc( hit_count1,
01775                                                          sizeof( fastf_t ), "dists1" );
01776                                         dists2 = (fastf_t *)bu_calloc( hit_count2,
01777                                                          sizeof( fastf_t ), "dists2" );
01778                                         VMOVE( start_pt, hits1[0] );
01779                                         dists1[0] = 0.0;
01780                                         min_dist = 0.0;
01781                                         min_hit = 0;
01782                                         VSUB2( dir, hits1[1], hits1[0] );
01783                                         dists1[1] = MAGNITUDE( dir );
01784                                         VUNITIZE( dir );
01785                                         max_dist = dists1[1];
01786                                         max_hit = 1;
01787                                         for( i=2 ; i<hit_count1 ; i++ ) {
01788                                                 VSUB2( diff, hits1[i], start_pt );
01789                                                 dists1[i] = MAGNITUDE( diff );
01790                                                 if( VDOT( dir, diff ) < 0.0 )
01791                                                         dists1[i] = -dists1[i];
01792                                                 if( dists1[i] > max_dist ) {
01793                                                         max_dist = dists1[i];
01794                                                         max_hit = i;
01795                                                 }
01796                                                 if( dists1[i] < min_dist ) {
01797                                                         min_dist = dists1[i];
01798                                                         min_hit = i;
01799                                                 }
01800                                         }
01801 
01802                                         /* recalculate dir */
01803                                         VSUB2( dir, hits1[max_hit], hits1[min_hit] );
01804                                         VUNITIZE( dir );
01805 
01806                                         done = 0;
01807                                         while( !done ) {
01808                                                 done = 1;
01809                                                 for( i=1 ; i<hit_count1 ; i++ ) {
01810                                                         if( dists1[i-1] > dists1[i] ) {
01811                                                                 fastf_t tmp;
01812                                                                 point_t tmp_pt;
01813 
01814                                                                 done = 0;
01815                                                                 tmp = dists1[i];
01816                                                                 VMOVE( tmp_pt, hits1[i] );
01817                                                                 dists1[i] = dists1[i-1];
01818                                                                 VMOVE( hits1[i], hits1[i-1] );
01819                                                                 dists1[i-1] = tmp;
01820                                                                 VMOVE( hits1[i-1], tmp_pt );
01821                                                         }
01822                                                 }
01823                                         }
01824 
01825                                         /* sort the hits on face 2 */
01826                                         min_dist = MAX_FASTF;
01827                                         min_hit = -1;
01828                                         max_dist = -min_dist;
01829                                         max_hit = -1;
01830                                         for( i=0 ; i<hit_count2 ; i++ ) {
01831                                                 VSUB2( diff, hits2[i], start_pt );
01832                                                 dists2[i] = MAGNITUDE( diff );
01833                                                 if( VDOT( dir, diff ) < 0.0 )
01834                                                         dists2[i] = -dists2[i];
01835                                                 if( dists2[i] > max_dist ) {
01836                                                         max_dist = dists2[i];
01837                                                         max_hit = i;
01838                                                 }
01839                                                 if( dists2[i] < min_dist ) {
01840                                                         min_dist = dists2[i];
01841                                                         min_hit = i;
01842                                                 }
01843                                         }
01844 
01845                                         done = 0;
01846                                         while( !done ) {
01847                                                 done = 1;
01848                                                 for( i=1 ; i<hit_count2 ; i++ ) {
01849                                                         if( dists2[i-1] > dists2[i] ) {
01850                                                                 fastf_t tmp;
01851                                                                 point_t tmp_pt;
01852 
01853                                                                 done = 0;
01854                                                                 tmp = dists2[i];
01855                                                                 VMOVE( tmp_pt, hits2[i] );
01856                                                                 dists2[i] = dists2[i-1];
01857                                                                 VMOVE( hits2[i], hits2[i-1] );
01858                                                                 dists2[i-1] = tmp;
01859                                                                 VMOVE( hits2[i-1], tmp_pt );
01860                                                         }
01861                                                 }
01862                                         }
01863 
01864                                         /* build a segment list for each solid */
01865                                         A = (struct bu_list *)bu_calloc( 1, sizeof( struct bu_list ), "A" );
01866                                         B = (struct bu_list *)bu_calloc( 1, sizeof( struct bu_list ), "B" );
01867                                         BU_LIST_INIT( A );
01868                                         BU_LIST_INIT( B );
01869 
01870                                         for( i=1 ; i<hit_count1 ; i += 2 ) {
01871                                                 fastf_t diff;
01872 
01873                                                 diff = dists1[i] - dists1[i-1];
01874                                                 if( NEAR_ZERO( diff, tol->dist )) {
01875                                                         continue;
01876                                                 }
01877                                                 RT_GET_SEG( aseg, dgcdp->ap->a_resource );
01878                                                 aseg->l.magic = RT_SEG_MAGIC;
01879                                                 aseg->seg_stp = ON_INT;
01880                                                 VMOVE( aseg->seg_in.hit_point, hits1[i-1] );
01881                                                 aseg->seg_in.hit_dist = dists1[i-1];
01882                                                 VMOVE( aseg->seg_out.hit_point, hits1[i] );
01883                                                 aseg->seg_out.hit_dist = dists1[i];
01884 
01885                                                 BU_LIST_APPEND( A, &aseg->l );
01886                                         }
01887 
01888                                         for( i=1 ; i<hit_count2 ; i += 2 ) {
01889                                                 fastf_t diff;
01890 
01891                                                 diff = dists2[i] - dists2[i-1];
01892                                                 if( NEAR_ZERO( diff, tol->dist )) {
01893                                                         continue;
01894                                                 }
01895                                                 RT_GET_SEG( aseg, dgcdp->ap->a_resource );
01896                                                 aseg->l.magic = RT_SEG_MAGIC;
01897                                                 aseg->seg_stp = ON_INT;
01898                                                 VMOVE( aseg->seg_in.hit_point, hits2[i-1] );
01899                                                 aseg->seg_in.hit_dist = dists2[i-1];
01900                                                 VMOVE( aseg->seg_out.hit_point, hits2[i] );
01901                                                 aseg->seg_out.hit_dist = dists2[i];
01902 
01903                                                 BU_LIST_APPEND( B, &aseg->l );
01904                                         }
01905 
01906                                         result = eval_op( A, OP_INTERSECT, B, dgcdp );
01907 
01908                                         for( BU_LIST_FOR( aseg, seg, result ) ) {
01909                                                 point_t ray_start;
01910 
01911                                                 VJOIN1( ray_start, start_pt, aseg->seg_in.hit_dist, dir );
01912                                                 shoot_and_plot( ray_start, dir, vhead,
01913                                                                 aseg->seg_out.hit_dist - aseg->seg_in.hit_dist,
01914                                                                 leaf_no, leaf2, eptr, ON_INT, dgcdp );
01915                                         }
01916                                         MY_FREE_SEG_LIST( result, dgcdp->ap->a_resource );
01917 
01918                                         bu_free( (char *)dists1, "dists1" );
01919                                         bu_free( (char *)dists2, "dists2" );
01920                                 }
01921                         }
01922                 }
01923         }
01924 
01925         bu_free( (char *)hits1, "hits1" );
01926         bu_free( (char *)hits2, "hits2" );
01927 }
01928 
01929 HIDDEN void
01930 free_etree(union E_tree                 *eptr,
01931            struct dg_client_data        *dgcdp)
01932 {
01933         CK_ETREE( eptr );
01934 
01935         switch( eptr->l.op )
01936         {
01937                 case OP_UNION:
01938                 case OP_SUBTRACT:
01939                 case OP_INTERSECT:
01940                         free_etree( eptr->n.left, dgcdp );
01941                         free_etree( eptr->n.right, dgcdp );
01942                         bu_free( (char *)eptr, "node pointer" );
01943                         break;
01944                 case OP_DB_LEAF:
01945                 case OP_SOLID:
01946                         if( eptr->l.m && !eptr->l.do_not_free_model )
01947                         {
01948                                 nmg_km( eptr->l.m );
01949                                 eptr->l.m = (struct model *)NULL;
01950                         }
01951                         if( BU_LIST_NON_EMPTY( &eptr->l.seghead ) )
01952                         {
01953                                 MY_FREE_SEG_LIST( &eptr->l.seghead, dgcdp->ap->a_resource );
01954                         }
01955                         if( BU_LIST_NON_EMPTY( &eptr->l.edge_list.l ) )
01956                         {
01957                                 bu_ptbl_free( &eptr->l.edge_list );
01958                         }
01959                         if( eptr->l.stp )
01960                         {
01961                                 if( eptr->l.stp->st_specific )
01962                                         rt_functab[eptr->l.stp->st_id].ft_free( eptr->l.stp );
01963                                 bu_free( (char *)eptr->l.stp, "struct soltab" );
01964                         }
01965 
01966                         bu_free( (char *)eptr, "leaf pointer" );
01967                         break;
01968         }
01969 }
01970 
01971 /* convert all "half" solids to polysolids */
01972 HIDDEN void
01973 fix_halfs(struct dg_client_data *dgcdp)
01974 {
01975         point_t max, min;
01976         int i, count=0;
01977         struct bn_tol *tol;
01978 
01979         tol = &dgcdp->dgop->dgo_wdbp->wdb_tol;
01980 
01981         VSETALL( max, -MAX_FASTF )
01982         VSETALL( min, MAX_FASTF )
01983 
01984         for( i=0 ; i<BU_PTBL_END( &dgcdp->leaf_list ) ; i++ )
01985         {
01986                 union E_tree *tp;
01987 
01988                 tp = (union E_tree *)BU_PTBL_GET( &dgcdp->leaf_list, i );
01989 
01990                 if( tp->l.stp->st_id == ID_HALF )
01991                         continue;
01992 
01993                 VMINMAX( min, max, tp->l.stp->st_min )
01994                 VMINMAX( min, max, tp->l.stp->st_max )
01995                 count++;
01996         }
01997 
01998         if( !count )
01999         {
02000                 Tcl_AppendResult(dgcdp->interp, "A 'half' solid is the only solid in a region (ignored)\n", (char *)NULL );
02001                 return;
02002         }
02003 
02004         for( i=0 ; i<BU_PTBL_END( &dgcdp->leaf_list ) ; i++ )
02005         {
02006                 union E_tree *tp;
02007                 struct vertex *v[8];
02008                 struct vertex **vp[4];
02009                 struct nmgregion *r;
02010                 struct shell *s;
02011                 struct rt_pg_internal *pg;
02012                 struct faceuse *fu;
02013                 plane_t haf_pl;
02014                 struct half_specific *hp;
02015                 int j;
02016 
02017                 tp = (union E_tree *)BU_PTBL_GET( &dgcdp->leaf_list, i );
02018 
02019                 if( tp->l.stp->st_id != ID_HALF )
02020                         continue;
02021 
02022                 hp = (struct half_specific *)tp->l.stp->st_specific;
02023 
02024                 HMOVE( haf_pl, hp->half_eqn )
02025 
02026                 if( DIST_PT_PLANE( max, haf_pl ) >= -tol->dist &&
02027                     DIST_PT_PLANE( min, haf_pl ) >= -tol->dist )
02028                         continue;
02029 
02030                 /* make an NMG the size of our model bounding box */
02031                 tp->l.m = nmg_mm();
02032                 r = nmg_mrsv( tp->l.m );
02033                 s = BU_LIST_FIRST( shell, &r->s_hd );
02034 
02035                 for( j=0 ; j<8 ; j++ )
02036                         v[j] = (struct vertex *)NULL;
02037 
02038                 vp[0] = &v[0];
02039                 vp[1] = &v[1];
02040                 vp[2] = &v[2];
02041                 vp[3] = &v[3];
02042                 fu = nmg_cmface( s, vp, 4 );
02043                 nmg_vertex_g( v[0], max[X], min[Y], min[Z] );
02044                 nmg_vertex_g( v[1], max[X], max[Y], min[Z] );
02045                 nmg_vertex_g( v[2], max[X], max[Y], max[Z] );
02046                 nmg_vertex_g( v[3], max[X], min[Y], max[Z] );
02047                 nmg_calc_face_g( fu );
02048 
02049                 vp[0] = &v[4];
02050                 vp[1] = &v[5];
02051                 vp[2] = &v[6];
02052                 vp[3] = &v[7];
02053                 fu = nmg_cmface( s, vp, 4 );
02054                 nmg_vertex_g( v[4], min[X], min[Y], min[Z] );
02055                 nmg_vertex_g( v[5], min[X], min[Y], max[Z] );
02056                 nmg_vertex_g( v[6], min[X], max[Y], max[Z] );
02057                 nmg_vertex_g( v[7], min[X], max[Y], min[Z] );
02058                 nmg_calc_face_g( fu );
02059 
02060                 vp[0] = &v[0];
02061                 vp[1] = &v[3];
02062                 vp[2] = &v[5];
02063                 vp[3] = &v[4];
02064                 fu = nmg_cmface( s, vp, 4 );
02065                 nmg_calc_face_g( fu );
02066 
02067                 vp[0] = &v[1];
02068                 vp[1] = &v[7];
02069                 vp[2] = &v[6];
02070                 vp[3] = &v[2];
02071                 fu = nmg_cmface( s, vp, 4 );
02072                 nmg_calc_face_g( fu );
02073 
02074                 vp[0] = &v[3];
02075                 vp[1] = &v[2];
02076                 vp[2] = &v[6];
02077                 vp[3] = &v[5];
02078                 fu = nmg_cmface( s, vp, 4 );
02079                 nmg_calc_face_g( fu );
02080 
02081                 vp[0] = &v[1];
02082                 vp[1] = &v[0];
02083                 vp[2] = &v[4];
02084                 vp[3] = &v[7];
02085                 fu = nmg_cmface( s, vp, 4 );
02086                 nmg_calc_face_g( fu );
02087 
02088                 nmg_region_a( r, tol );
02089 
02090                 for( BU_LIST_FOR( fu, faceuse, &s->fu_hd ) )
02091                 {
02092                         struct edgeuse *eu, *new_eu;
02093                         struct loopuse *lu, *new_lu;
02094                         plane_t pl;
02095                         int count;
02096                         struct vertexuse *vcut[2];
02097                         point_t pt[2];
02098                         struct edgeuse *eu_split[2];
02099 
02100                         if( fu->orientation != OT_SAME )
02101                                 continue;
02102 
02103                         NMG_GET_FU_PLANE( pl, fu );
02104 
02105                         if( bn_coplanar( pl, haf_pl, tol ) > 0 )
02106                                 continue;
02107 
02108                         lu = BU_LIST_FIRST( loopuse, &fu->lu_hd );
02109 
02110                         count = 0;
02111                         for( BU_LIST_FOR( eu, edgeuse, &lu->down_hd ) )
02112                         {
02113                                 vect_t dir;
02114                                 struct vertex_g *v1g, *v2g;
02115                                 fastf_t dist;
02116 
02117                                 v1g = eu->vu_p->v_p->vg_p;
02118                                 v2g = eu->eumate_p->vu_p->v_p->vg_p;
02119 
02120                                 VSUB2( dir, v2g->coord, v1g->coord )
02121 
02122                                 if( bn_isect_line3_plane( &dist, v1g->coord, dir, haf_pl, tol ) < 1 )
02123                                         continue;
02124 
02125                                 if( dist < 0.0 || dist >=1.0 )
02126                                         continue;
02127 
02128                                 VJOIN1( pt[count], v1g->coord, dist, dir )
02129                                 eu_split[count] = eu;
02130 
02131                                 count++;
02132                                 if( count == 2 )
02133                                         break;
02134                         }
02135 
02136                         if( count != 2 )
02137                                 continue;
02138 
02139                         new_eu = nmg_eusplit( (struct vertex *)NULL, eu_split[0], 1 );
02140                         vcut[0] = new_eu->vu_p;
02141                         nmg_vertex_gv( vcut[0]->v_p, pt[0] );
02142 
02143                         new_eu = nmg_eusplit( (struct vertex *)NULL, eu_split[1], 1 );
02144                         vcut[1] = new_eu->vu_p;
02145                         nmg_vertex_gv( vcut[1]->v_p, pt[1] );
02146 
02147                         new_lu = nmg_cut_loop( vcut[0], vcut[1] );
02148                         nmg_lu_reorient( lu );
02149                         nmg_lu_reorient( new_lu );
02150 
02151                         for( BU_LIST_FOR( eu, edgeuse, &lu->down_hd ) )
02152                         {
02153                                 if( eu->vu_p->v_p == vcut[0]->v_p || eu->vu_p->v_p == vcut[1]->v_p )
02154                                         continue;
02155 
02156                                 if( DIST_PT_PLANE( eu->vu_p->v_p->vg_p->coord, haf_pl ) > tol->dist )
02157                                 {
02158                                         nmg_klu( lu );
02159                                         break;
02160                                 }
02161                                 else
02162                                 {
02163                                         nmg_klu( new_lu );
02164                                         break;
02165                                 }
02166                         }
02167                 }
02168 
02169                 /* kill any faces outside the half */
02170                 fu = BU_LIST_FIRST( faceuse, &s->fu_hd );
02171                 if( fu->orientation != OT_SAME )
02172                         fu = BU_LIST_PNEXT( faceuse, &fu->l );
02173                 while( BU_LIST_NOT_HEAD( &fu->l, &s->fu_hd ) )
02174                 {
02175                         struct faceuse *next_fu;
02176                         struct loopuse *lu;
02177                         int killfu=0;
02178 
02179                         next_fu = BU_LIST_PNEXT( faceuse, &fu->l );
02180                         if( fu->fumate_p == next_fu )
02181                                 next_fu = BU_LIST_PNEXT( faceuse, &next_fu->l );
02182 
02183                         if( fu->orientation != OT_SAME )
02184                         {
02185                                 fu = next_fu;
02186                                 continue;
02187                         }
02188 
02189                         lu = BU_LIST_FIRST( loopuse, &fu->lu_hd );
02190                         while( BU_LIST_NOT_HEAD( &lu->l, &fu->lu_hd ) )
02191                         {
02192                                 struct loopuse *next_lu;
02193                                 struct edgeuse *eu;
02194                                 int killit;
02195 
02196                                 next_lu = BU_LIST_PNEXT( loopuse, &lu->l );
02197 
02198                                 killit = 0;
02199                                 for( BU_LIST_FOR( eu, edgeuse, &lu->down_hd ) )
02200                                 {
02201                                         struct vertex_g *vg;
02202 
02203                                         vg = eu->vu_p->v_p->vg_p;
02204 
02205                                         if( DIST_PT_PLANE( vg->coord, haf_pl ) > tol->dist )
02206                                         {
02207                                                 killit = 1;
02208                                                 break;
02209                                         }
02210                                 }
02211 
02212                                 if( killit )
02213                                 {
02214                                         if( nmg_klu( lu ) )
02215                                         {
02216                                                 killfu = 1;
02217                                                 break;
02218                                         }
02219                                 }
02220                                 lu = next_lu;
02221                         }
02222 
02223                         if( killfu )
02224                                 nmg_kfu( fu );
02225 
02226                         fu = next_fu;
02227                 }
02228 
02229                 nmg_rebound( tp->l.m, tol );
02230                 nmg_model_fuse( tp->l.m, tol );
02231                 nmg_close_shell( s, tol );
02232                 nmg_rebound( tp->l.m, tol );
02233 
02234                 BU_GETSTRUCT( pg, rt_pg_internal );
02235 
02236                 if( !nmg_to_poly( tp->l.m, pg, tol ) )
02237                 {
02238                         bu_free( (char *)pg, "rt_pg_internal" );
02239                         Tcl_AppendResult(dgcdp->interp, "Prep failure for solid '", tp->l.stp->st_dp->d_namep,
02240                                 "'\n", (char *)NULL );
02241                 }
02242                 else
02243                 {
02244                         struct rt_db_internal intern2;
02245 
02246                         RT_INIT_DB_INTERNAL( &intern2 );
02247                         intern2.idb_major_type = DB5_MAJORTYPE_BRLCAD;
02248                         intern2.idb_type = ID_POLY;
02249                         intern2.idb_meth = &rt_functab[ID_POLY];
02250                         intern2.idb_ptr = (genptr_t)pg;
02251                         rt_functab[tp->l.stp->st_id].ft_free( tp->l.stp );
02252                         tp->l.stp->st_specific = NULL;
02253                         tp->l.stp->st_id = ID_POLY;
02254                         VSETALL( tp->l.stp->st_max, -INFINITY );
02255                         VSETALL( tp->l.stp->st_min,  INFINITY );
02256                         if (rt_functab[ID_POLY].ft_prep( tp->l.stp, &intern2, dgcdp->rtip ) < 0 )
02257                         {
02258                                 Tcl_AppendResult(dgcdp->interp, "Prep failure for polysolid version of solid '", tp->l.stp->st_dp->d_namep,
02259                                         "'\n", (char *)NULL );
02260                         }
02261 
02262                         rt_db_free_internal( &intern2, &rt_uniresource );
02263                 }
02264         }
02265 }
02266 
02267 int
02268 dgo_E_cmd(struct dg_obj *dgop,
02269          Tcl_Interp     *interp,
02270          int            argc,
02271          char           **argv)
02272 {
02273         register int            c;
02274         char                    perf_message[128];
02275         struct dg_client_data   *dgcdp;
02276 
02277         if (argc < 2) {
02278                 struct bu_vls vls;
02279 
02280                 bu_vls_init(&vls);
02281                 bu_vls_printf(&vls, "help E");
02282                 Tcl_Eval(interp, bu_vls_addr(&vls));
02283                 bu_vls_free(&vls);
02284                 return TCL_ERROR;
02285         }
02286 
02287         if (bu_debug&BU_DEBUG_MEM_CHECK && bu_mem_barriercheck())
02288                 bu_log("Error at start of 'E'\n");
02289 
02290         BU_GETSTRUCT(dgcdp, dg_client_data);
02291         dgcdp->dgop = dgop;
02292         dgcdp->interp = interp;
02293         dgcdp->do_polysolids = 0;
02294         dgcdp->wireframe_color_override = 0;
02295 
02296         /* Parse options. */
02297         bu_optind = 1;          /* re-init bu_getopt() */
02298         while((c=bu_getopt(argc,argv,"sC:")) != EOF) {
02299                 switch (c) {
02300                 case 'C':
02301                         {
02302                                 int             r,g,b;
02303                                 register char   *cp = bu_optarg;
02304 
02305                                 r = atoi(cp);
02306                                 while((*cp >= '0' && *cp <= '9'))  cp++;
02307                                 while(*cp && (*cp < '0' || *cp > '9')) cp++;
02308                                 g = atoi(cp);
02309                                 while((*cp >= '0' && *cp <= '9'))  cp++;
02310                                 while(*cp && (*cp < '0' || *cp > '9')) cp++;
02311                                 b = atoi(cp);
02312 
02313                                 if (r < 0 || r > 255)  r = 255;
02314                                 if (g < 0 || g > 255)  g = 255;
02315                                 if (b < 0 || b > 255)  b = 255;
02316 
02317                                 dgcdp->wireframe_color_override = 1;
02318                                 dgcdp->wireframe_color[0] = r;
02319                                 dgcdp->wireframe_color[1] = g;
02320                                 dgcdp->wireframe_color[2] = b;
02321                         }
02322                         break;
02323                 case 's':
02324                         dgcdp->do_polysolids = 1;
02325                         break;
02326                 default:
02327                         {
02328                                 struct bu_vls vls;
02329 
02330                                 bu_vls_init(&vls);
02331                                 bu_vls_printf(&vls, "help %s", argv[0]);
02332                                 Tcl_Eval(interp, bu_vls_addr(&vls));
02333                                 bu_vls_free(&vls);
02334 
02335                                 return TCL_ERROR;
02336                         }
02337                 }
02338         }
02339         argc -= bu_optind;
02340         argv += bu_optind;
02341 
02342         dgo_eraseobjpath(dgop, interp, argc, argv, LOOKUP_QUIET, 0);
02343 
02344 #if 0
02345         dgop->dgo_wdbp->wdb_ttol.magic = RT_TESS_TOL_MAGIC;
02346         dgop->dgo_wdbp->wdb_ttol.rel = 0.01;
02347 #endif
02348 
02349         dgcdp->ap = (struct application *)bu_malloc(sizeof(struct application), "Big E app");
02350         RT_APPLICATION_INIT(dgcdp->ap);
02351         dgcdp->ap->a_resource = &rt_uniresource;
02352         rt_uniresource.re_magic = RESOURCE_MAGIC;
02353         if( BU_LIST_UNINITIALIZED( &rt_uniresource.re_nmgfree ) )
02354                 BU_LIST_INIT( &rt_uniresource.re_nmgfree );
02355 
02356         bu_ptbl_init( &dgcdp->leaf_list, 8, "leaf_list" );
02357 
02358         dgcdp->rtip = rt_new_rti( dgop->dgo_wdbp->dbip );
02359         dgcdp->rtip->rti_tol = dgop->dgo_wdbp->wdb_tol; /* struct copy */
02360         dgcdp->rtip->useair = 1;
02361         dgcdp->ap->a_rt_i = dgcdp->rtip;
02362 
02363         dgcdp->nvectors = 0;
02364         (void)time( &dgcdp->start_time );
02365 
02366         if( rt_gettrees( dgcdp->rtip, argc, (const char **)argv, 1 ) )
02367         {
02368                 bu_ptbl_free( &dgcdp->leaf_list );
02369 
02370                 /* do not do an rt_free_rti() (closes the database!!!!) */
02371                 rt_clean( dgcdp->rtip );
02372 
02373                 bu_free( (char *)dgcdp->rtip, "rt_i structure for 'E'" );
02374                 bu_free(dgcdp, "dgcdp");
02375 
02376                 Tcl_AppendResult(interp, "Failed to get objects\n", (char *)NULL);
02377                 return TCL_ERROR;
02378         }
02379         {
02380                 struct region *rp;
02381                 union E_tree *eptr;
02382                 struct bu_list vhead;
02383                 struct db_tree_state ts;
02384                 struct db_full_path path;
02385 
02386                 BU_LIST_INIT( &vhead );
02387 
02388                 for( BU_LIST_FOR( rp, region, &(dgcdp->rtip->HeadRegion) ) )  {
02389                         dgcdp->num_halfs = 0;
02390                         eptr = build_etree( rp->reg_treetop, dgcdp );
02391 
02392                         if( dgcdp->num_halfs )
02393                                 fix_halfs(dgcdp);
02394 
02395                         Eplot( eptr, &vhead, dgcdp );
02396                         free_etree( eptr, dgcdp );
02397                         bu_ptbl_reset( &dgcdp->leaf_list );
02398                         ts.ts_mater = rp->reg_mater;
02399                         db_string_to_path( &path, dgop->dgo_wdbp->dbip, rp->reg_name );
02400                         dgo_drawH_part2( 0, &vhead, &path, &ts, SOLID_NULL, dgcdp );
02401                         db_free_full_path( &path );
02402                 }
02403                 /* do not do an rt_free_rti() (closes the database!!!!) */
02404                 rt_clean( dgcdp->rtip );
02405 
02406                 bu_free( (char *)dgcdp->rtip, "rt_i structure for 'E'" );
02407         }
02408 
02409         dgo_color_soltab(&dgop->dgo_headSolid);
02410         (void)time( &dgcdp->etime );
02411 
02412         /* free leaf_list */
02413         bu_ptbl_free( &dgcdp->leaf_list );
02414 
02415         sprintf(perf_message, "E: %ld vectors in %ld sec\n", dgcdp->nvectors, (long)(dgcdp->etime - dgcdp->start_time) );
02416         Tcl_AppendResult(interp, perf_message, (char *)NULL);
02417 
02418         return TCL_OK;
02419 }
02420 
02421 /*
02422  *                      F _ E V E D I T
02423  *
02424  *  The "Big E" command.
02425  *  Evaluated Edit something (add to visible display)
02426  *  Usage: E object(s)
02427  */
02428 int
02429 dgo_E_tcl(ClientData    clientData,
02430           Tcl_Interp    *interp,
02431           int           argc,
02432           char          **argv)
02433 {
02434         struct dg_obj           *dgop = (struct dg_obj *)clientData;
02435 
02436         return dgo_E_cmd(dgop, interp, argc-1, argv+1);
02437 }
02438 
02439 /*
02440  * Local Variables:
02441  * mode: C
02442  * tab-width: 8
02443  * c-basic-offset: 4
02444  * indent-tabs-mode: t
02445  * End:
02446  * ex: shiftwidth=4 tabstop=8
02447  */

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