nmg_rt_segs.c

Go to the documentation of this file.
00001 /*                   N M G _ R T _ S E G S . C
00002  * BRL-CAD
00003  *
00004  * Copyright (c) 1993-2006 United States Government as represented by
00005  * the U.S. Army Research Laboratory.
00006  *
00007  * This library is free software; you can redistribute it and/or
00008  * modify it under the terms of the GNU Lesser General Public License
00009  * as published by the Free Software Foundation; either version 2 of
00010  * the License, or (at your option) any later version.
00011  *
00012  * This library is distributed in the hope that it will be useful, but
00013  * WITHOUT ANY WARRANTY; without even the implied warranty of
00014  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
00015  * Library General Public License for more details.
00016  *
00017  * You should have received a copy of the GNU Lesser General Public
00018  * License along with this file; see the file named COPYING for more
00019  * information.
00020  */
00021 /** @addtogroup nmg */
00022 /*@{*/
00023 /** @file nmg_rt_segs.c
00024  *      Support routines for raytracing an NMG.
00025  *
00026  *  Author -
00027  *      Lee A. Butler
00028  *
00029  *  Source -
00030  *      The U. S. Army Research Laboratory
00031  *      Aberdeen Proving Ground, Maryland  21005-5066  USA
00032  *
00033  */
00034 /*@}*/
00035 #ifndef lint
00036 static const char RCSid[] = "@(#)$Header: /cvsroot/brlcad/brlcad/src/librt/nmg_rt_segs.c,v 14.13 2006/09/16 02:04:25 lbutler Exp $ (BRL)";
00037 #endif
00038 
00039 #include "common.h"
00040 
00041 #include <stdlib.h>
00042 #include <stddef.h>
00043 #include <stdio.h>
00044 #include <string.h>
00045 #include <math.h>
00046 
00047 #include "machine.h"
00048 #include "vmath.h"
00049 #include "nmg.h"
00050 #include "raytrace.h"
00051 #include "plot3.h"
00052 
00053 
00054 /*      EDGE-FACE correlation data
00055  *      used in edge_hit() for 3manifold case
00056  */
00057 struct ef_data {
00058         fastf_t         fdotr;  /* face vector VDOT with ray */
00059         fastf_t         fdotl;  /* face vector VDOT with ray-left */
00060         fastf_t         ndotr;  /* face normal VDOT with ray */
00061         struct edgeuse *eu;
00062 };
00063 
00064 #if 0
00065 static const
00066 struct bu_structparse rt_ef_parsetab[] = {
00067         {"%f", 1, "fdotr", bu_offsetof(struct ef_data, fdotr), BU_STRUCTPARSE_FUNC_NULL},
00068         {"%f", 1, "fdotl", bu_offsetof(struct ef_data, fdotl), BU_STRUCTPARSE_FUNC_NULL},
00069         {"%f", 1, "ndotr", bu_offsetof(struct ef_data, ndotr), BU_STRUCTPARSE_FUNC_NULL},
00070         {"%x", 1, "eu",   bu_offsetof(struct ef_data, eu),   BU_STRUCTPARSE_FUNC_NULL},
00071         {"", 0, (char *)NULL,     0,                      BU_STRUCTPARSE_FUNC_NULL}
00072 };
00073 
00074 static const
00075 struct bu_structparse rt_hit_parsetab[] = {
00076 {"%f", 1, "hit_dist", bu_offsetof(struct hit, hit_dist), BU_STRUCTPARSE_FUNC_NULL},
00077 {"%f", 3, "hit_point", bu_offsetofarray(struct hit, hit_point), BU_STRUCTPARSE_FUNC_NULL},
00078 {"%f", 4, "hit_normal", bu_offsetofarray(struct hit, hit_normal), BU_STRUCTPARSE_FUNC_NULL},
00079 {"%f", 3, "hit_vpriv", bu_offsetofarray(struct hit, hit_vpriv), BU_STRUCTPARSE_FUNC_NULL},
00080 {"%x", 1, "hit_private", bu_offsetof(struct hit, hit_private), BU_STRUCTPARSE_FUNC_NULL},
00081 {"%d", 1, "hit_surfno", bu_offsetof(struct hit, hit_surfno), BU_STRUCTPARSE_FUNC_NULL},
00082 {"", 0, (char *)NULL,     0,                      BU_STRUCTPARSE_FUNC_NULL}
00083 };
00084 #endif
00085 
00086 #define CK_SEGP(_p) if ( !(_p) || !(*(_p)) ) {\
00087         bu_log("%s[line:%d]: Bad seg_p pointer\n", __FILE__, __LINE__); \
00088         nmg_rt_segs_exit("Goodbye"); }
00089 #define DO_LONGJMP
00090 #ifdef DO_LONGJMP
00091 jmp_buf nmg_longjump_env;
00092 #define nmg_rt_segs_exit(_s) {bu_log("%s\n",_s);longjmp(nmg_longjump_env, -1);}
00093 #else
00094 #define nmg_rt_segs_exit(_s) rt_bomb(_s)
00095 #endif
00096 
00097 
00098 
00099 static void
00100 print_seg_list(struct seg *seghead, int seg_count, char *s)
00101 {
00102         struct seg *seg_p;
00103 
00104         bu_log("Segment List (%d segnemts) (%s):\n", seg_count, s);
00105         /* print debugging data before returning */
00106         bu_log("Seghead:\n0x%08x magic: 0x%0x(%d) forw:0x%08x back:0x%08x\n\n",
00107                         seghead,
00108                         seghead->l.magic,
00109                         seghead->l.forw,
00110                         seghead->l.back);
00111 
00112         for (BU_LIST_FOR(seg_p, seg, &seghead->l) ) {
00113                 bu_log("0x%08x magic: 0x%0x(%d) forw:0x%08x back:0x%08x\n",
00114                         seg_p,
00115                         seg_p->l.magic,
00116                         seg_p->l.forw,
00117                         seg_p->l.back);
00118                 bu_log("dist %g  pt(%g,%g,%g)  N(%g,%g,%g)  =>\n",
00119                 seg_p->seg_in.hit_dist,
00120                 seg_p->seg_in.hit_point[0],
00121                 seg_p->seg_in.hit_point[1],
00122                 seg_p->seg_in.hit_point[2],
00123                 seg_p->seg_in.hit_normal[0],
00124                 seg_p->seg_in.hit_normal[1],
00125                 seg_p->seg_in.hit_normal[2]);
00126                 bu_log("dist %g  pt(%g,%g,%g)  N(%g,%g,%g)\n",
00127                 seg_p->seg_out.hit_dist,
00128                 seg_p->seg_out.hit_point[0],
00129                 seg_p->seg_out.hit_point[1],
00130                 seg_p->seg_out.hit_point[2],
00131                 seg_p->seg_out.hit_normal[0],
00132                 seg_p->seg_out.hit_normal[1],
00133                 seg_p->seg_out.hit_normal[2]);
00134         }
00135 }
00136 
00137 static void
00138 pl_ray(struct ray_data *rd)
00139 {
00140         FILE *fd;
00141         char name[80];
00142         static int plot_file_number=0;
00143         struct hitmiss *a_hit;
00144         int old_state = NMG_RAY_STATE_OUTSIDE;
00145         int in_state;
00146         int out_state;
00147         point_t old_point;
00148         point_t end_point;
00149         int old_cond = 0;
00150 
00151         sprintf(name, "nmg_ray%02d.pl", plot_file_number++);
00152         if ((fd=fopen(name, "w")) == (FILE *)NULL) {
00153                 perror(name);
00154                 bu_bomb("unable to open file for writing");
00155         } else {
00156                 bu_log("overlay %s\n", name);
00157         }
00158 
00159         VMOVE(old_point, rd->rp->r_pt);
00160 
00161         for (BU_LIST_FOR(a_hit, hitmiss, &rd->rd_hit)) {
00162 #ifndef FAST_NMG
00163                 NMG_CK_HITMISS(a_hit);
00164 #endif
00165 
00166                 in_state = HMG_INBOUND_STATE(a_hit);
00167                 out_state = HMG_OUTBOUND_STATE(a_hit);
00168 
00169                 if (in_state == old_state) {
00170                         switch(in_state) {
00171                         case NMG_RAY_STATE_INSIDE:
00172                                 pl_color(fd, 55, 255, 55);
00173                                 pdv_3line(fd, old_point, a_hit->hit.hit_point);
00174                                 break;
00175                         case NMG_RAY_STATE_ON:
00176                                 pl_color(fd, 155, 155, 255);
00177                                 pdv_3line(fd, old_point, a_hit->hit.hit_point);
00178                                 break;
00179                         case NMG_RAY_STATE_OUTSIDE:
00180                                 pl_color(fd, 255, 255, 255);
00181                                 pdv_3line(fd, old_point, a_hit->hit.hit_point);
00182                                 break;
00183                         }
00184                         old_cond = 0;
00185                 } else {
00186                         if (old_cond) {
00187                                 pl_color(fd, 255, 155, 255);
00188                                 old_cond = 0;
00189                         } else {
00190                                 pl_color(fd, 255, 55, 255);
00191                                 old_cond = 1;
00192                         }
00193                         pdv_3line(fd, old_point, a_hit->hit.hit_point);
00194                 }
00195                 VMOVE(old_point, a_hit->hit.hit_point);
00196                 old_state = out_state;
00197         }
00198 
00199         if (old_state == NMG_RAY_STATE_OUTSIDE)
00200                 pl_color(fd, 255, 255, 255);
00201         else
00202                 pl_color(fd, 255, 55, 255);
00203 
00204         VADD2(end_point, old_point, rd->rp->r_dir);
00205         pdv_3line(fd, old_point, end_point);
00206 
00207         fclose(fd);
00208 }
00209 
00210 /*
00211  *              N E X T _ S T A T E _ T A B L E
00212  *
00213  *                      Current_State
00214  *      Input   |  0   1     2    3    4    5    6
00215  *      -------------------------------------------
00216  *      O_N  =  | i1   1   Ci1    5    1    5    5
00217  *      O_N !=  | i1  1|E  Ci1   C1  Ci1  Ci1  Ci1
00218  *      N_N  =  |  E   1     E    3    E    1    1
00219  *      N_N !=  |  E   1     E    E    E    1    1
00220  *      N_O  =  |  E  o2    o2  ?o2    E   o2   o2
00221  *      N_O !=  |  E  o2    o2    E    E   o2   o2
00222  *      O_O  =  |io3  o2    o2    3    3    6    6
00223  *      O_O !=  |io3 o2|E Cio3 Cio3 Cio3 Cio3 Cio3
00224  *      A_A  =  |io4   1     2    3    4    5    6
00225  *      A_A !=  |io4   1  Cio4 Cio4 Cio4 Cio4 Cio4
00226  *      EOI     |  N   E    CN   CN   CN   CN   CN
00227  *
00228  *      =       -> ray dist to point within tol (along ray) of last hit point
00229  *      !=      -> ray dist to point outside tol (along ray) of last hit point
00230  *
00231  *      State Prefix
00232  *      C       segment now completed, add to list & alloc new segment
00233  *      i       set inpoint for current segment
00234  *      o       set outpoint for current segment
00235  *
00236  *      State
00237  *      E       Error termination
00238  *      N       Normal termination
00239  *      1       "Entering" solid
00240  *      2       "Leaving" solid
00241  *      3       O_O from outside state
00242  *      4       A_A from outside state
00243  *      5       O_O=O_N         Fuzzy state 1 or state 2 from state 3
00244  *      6       0_0=O_N=O_O
00245  */
00246 
00247 
00248 static void
00249 set_inpoint(struct seg **seg_p, struct hitmiss *a_hit, struct soltab *stp, struct application *ap)
00250                                 /* The segment we're building */
00251                                 /* The input hit point */
00252 
00253 
00254 {
00255         if ( !seg_p ) {
00256                 bu_log("%s[line:%d]: Null pointer to segment pointer\n",
00257                         __FILE__, __LINE__);
00258                 nmg_rt_segs_exit("Goodbye");
00259         }
00260 
00261         /* if we don't have a seg struct yet, get one */
00262         if ( *seg_p == (struct seg *)NULL ) {
00263                 RT_GET_SEG(*seg_p, ap->a_resource);
00264                 (*seg_p)->seg_stp = stp;
00265         }
00266 
00267         /* copy the "in" hit */
00268         bcopy(&a_hit->hit, &(*seg_p)->seg_in, sizeof(struct hit));
00269 
00270         /* copy the normal */
00271         VMOVE((*seg_p)->seg_in.hit_normal, a_hit->inbound_norm);
00272 
00273         if (rt_g.NMG_debug & DEBUG_RT_SEGS) {
00274                 bu_log("Set seg_in:\n\tdist %g  pt(%g,%g,%g)  N(%g,%g,%g)\n",
00275                 (*seg_p)->seg_in.hit_dist,
00276                 (*seg_p)->seg_in.hit_point[0],
00277                 (*seg_p)->seg_in.hit_point[1],
00278                 (*seg_p)->seg_in.hit_point[2],
00279                 (*seg_p)->seg_in.hit_normal[0],
00280                 (*seg_p)->seg_in.hit_normal[1],
00281                 (*seg_p)->seg_in.hit_normal[2]);
00282         }
00283 }
00284 
00285 static void
00286 set_outpoint(struct seg **seg_p, struct hitmiss *a_hit)
00287                                 /* The segment we're building */
00288                                 /* The input hit point */
00289 {
00290         if ( !seg_p ) {
00291                 bu_log("%s[line:%d]: Null pointer to segment pointer\n",
00292                         __FILE__, __LINE__);
00293                 nmg_rt_segs_exit("Goodbye");
00294         }
00295 
00296         /* if we don't have a seg struct yet, get one */
00297         if ( *seg_p == (struct seg *)NULL )
00298                 nmg_rt_segs_exit("bad seg pointer\n");
00299 
00300         /* copy the "out" hit */
00301         bcopy(&a_hit->hit, &(*seg_p)->seg_out, sizeof(struct hit));
00302 
00303         /* copy the normal */
00304         VMOVE((*seg_p)->seg_out.hit_normal, a_hit->outbound_norm);
00305 
00306         if (rt_g.NMG_debug & DEBUG_RT_SEGS) {
00307                 bu_log("Set seg_out:\n\tdist %g  pt(%g,%g,%g)  N(%g,%g,%g)  =>\n",
00308                 (*seg_p)->seg_in.hit_dist,
00309                 (*seg_p)->seg_in.hit_point[0],
00310                 (*seg_p)->seg_in.hit_point[1],
00311                 (*seg_p)->seg_in.hit_point[2],
00312                 (*seg_p)->seg_in.hit_normal[0],
00313                 (*seg_p)->seg_in.hit_normal[1],
00314                 (*seg_p)->seg_in.hit_normal[2]);
00315                 bu_log("\tdist %g  pt(%g,%g,%g)  N(%g,%g,%g)\n",
00316                 (*seg_p)->seg_out.hit_dist,
00317                 (*seg_p)->seg_out.hit_point[0],
00318                 (*seg_p)->seg_out.hit_point[1],
00319                 (*seg_p)->seg_out.hit_point[2],
00320                 (*seg_p)->seg_out.hit_normal[0],
00321                 (*seg_p)->seg_out.hit_normal[1],
00322                 (*seg_p)->seg_out.hit_normal[2]);
00323         }
00324 }
00325 
00326 
00327 
00328 static int
00329 state0(struct seg *seghead, struct seg **seg_p, int *seg_count, struct hitmiss *a_hit, struct soltab *stp, struct application *ap, struct bn_tol *tol)
00330                                 /* intersection w/ ray */
00331                                 /* The segment we're building */
00332                                 /* The number of valid segments built */
00333                                 /* The input hit point */
00334 
00335 
00336 
00337 {
00338         int ret_val = -1;
00339 
00340         switch (a_hit->in_out) {
00341         case HMG_HIT_OUT_IN:
00342         case HMG_HIT_OUT_ON:
00343                 /* save the in-hit point */
00344                 set_inpoint(seg_p, a_hit, stp, ap);
00345                 ret_val = 1;
00346                 break;
00347         case HMG_HIT_ON_ON:
00348         case HMG_HIT_IN_IN:
00349         case HMG_HIT_ON_IN:
00350         case HMG_HIT_IN_ON:
00351         case HMG_HIT_IN_OUT:
00352         case HMG_HIT_ON_OUT:
00353                 /* error */
00354                 bu_log("%s[line:%d]: State transition error: exit without entry.\n",
00355                         __FILE__, __LINE__);
00356                 ret_val = -2;
00357                 break;
00358         case HMG_HIT_OUT_OUT:
00359                 /* Save the in/out points */
00360                 set_inpoint(seg_p, a_hit, stp, ap);
00361                 set_outpoint(seg_p, a_hit);
00362                 ret_val = 3;
00363                 break;
00364         case HMG_HIT_ANY_ANY:
00365                 /* Save the in/out points */
00366                 set_inpoint(seg_p, a_hit, stp, ap);
00367                 set_outpoint(seg_p, a_hit);
00368                 ret_val = 4;
00369                 break;
00370         default:
00371                 bu_log("%s[line:%d]: bogus hit in/out status\n",
00372                         __FILE__, __LINE__);
00373                 nmg_rt_segs_exit("Goodbye\n");
00374                 break;
00375         }
00376 
00377         return ret_val;
00378 }
00379 
00380 static int
00381 state1(struct seg *seghead, struct seg **seg_p, int *seg_count, struct hitmiss *a_hit, struct soltab *stp, struct application *ap, struct bn_tol *tol)
00382                                 /* intersection w/ ray */
00383                                 /* The segment we're building */
00384                                 /* The number of valid segments built */
00385                                 /* The input hit point */
00386 
00387 
00388 
00389 {
00390         int ret_val = -1;
00391 
00392         switch (a_hit->in_out) {
00393         case HMG_HIT_OUT_ON:
00394         case HMG_HIT_OUT_IN:
00395         case HMG_HIT_IN_IN:
00396         case HMG_HIT_ON_IN:
00397         case HMG_HIT_IN_ON:
00398         case HMG_HIT_ON_ON:
00399                 ret_val = 1;
00400                 break;
00401         case HMG_HIT_ON_OUT:
00402         case HMG_HIT_IN_OUT:
00403                 set_outpoint(seg_p, a_hit);
00404                 ret_val = 2;
00405                 break;
00406         case HMG_HIT_OUT_OUT:
00407                 /* XXX possibly an error condition if not within tol */
00408                 set_outpoint(seg_p, a_hit);
00409                 ret_val = 2;
00410                 break;
00411         case HMG_HIT_ANY_ANY:
00412                 ret_val = 1;
00413                 break;
00414         default:
00415                 bu_log("%s[line:%d]: bogus hit in/out status\n",
00416                         __FILE__, __LINE__);
00417                 nmg_rt_segs_exit("Goodbye\n");
00418                 break;
00419         }
00420 
00421         return ret_val;
00422 }
00423 
00424 static int
00425 state2(struct seg *seghead, struct seg **seg_p, int *seg_count, struct hitmiss *a_hit, struct soltab *stp, struct application *ap, struct bn_tol *tol)
00426                                 /* intersection w/ ray */
00427                                 /* The segment we're building */
00428                                 /* The number of valid segments built */
00429                                 /* The input hit point */
00430 
00431 
00432 
00433 {
00434         int ret_val = -1;
00435         double delta;
00436 
00437         switch (a_hit->in_out) {
00438         case HMG_HIT_OUT_ON:
00439         case HMG_HIT_OUT_IN:
00440                 /* Segment completed.  Insert into segment list */
00441                 BU_LIST_MAGIC_SET( &( (*seg_p)->l ), RT_SEG_MAGIC);
00442                 BU_LIST_INSERT(&(seghead->l), &((*seg_p)->l) );
00443                 (*seg_count)++;
00444 
00445                 /* start new segment */
00446                 (*seg_p) = (struct seg *)NULL;
00447                 set_inpoint(seg_p, a_hit, stp, ap);
00448 
00449                 ret_val = 1;
00450                 break;
00451         case HMG_HIT_IN_IN:
00452         case HMG_HIT_ON_ON:
00453         case HMG_HIT_ON_IN:
00454         case HMG_HIT_IN_ON:
00455                 /* Error */
00456                 bu_log("%s[line:%d]: State transition error.\n",
00457                         __FILE__, __LINE__);
00458                 ret_val = -2;
00459                 break;
00460         case HMG_HIT_ON_OUT:
00461         case HMG_HIT_IN_OUT:
00462                 /* progress the out-point */
00463                 set_outpoint(seg_p, a_hit);
00464                 ret_val = 2;
00465                 break;
00466         case HMG_HIT_OUT_OUT:
00467                 CK_SEGP(seg_p);
00468                 BN_CK_TOL(tol);
00469                 delta = fabs((*seg_p)->seg_in.hit_dist - a_hit->hit.hit_dist);
00470                 if ( delta < tol->dist) {
00471                         set_outpoint(seg_p, a_hit);
00472                         ret_val = 2;
00473                         break;
00474                 }
00475                 /* complete the segment */
00476                 BU_LIST_MAGIC_SET( &( (*seg_p)->l ), RT_SEG_MAGIC);
00477                 BU_LIST_INSERT(&(seghead->l), &((*seg_p)->l) );
00478                 (*seg_count)++;
00479 
00480                 /* start new segment */
00481                 (*seg_p) = (struct seg *)NULL;
00482                 set_inpoint(seg_p, a_hit, stp, ap);
00483                 set_outpoint(seg_p, a_hit);
00484 
00485                 ret_val = 3;
00486                 break;
00487         case HMG_HIT_ANY_ANY:
00488                 CK_SEGP(seg_p);
00489                 BN_CK_TOL(tol);
00490                 delta = fabs((*seg_p)->seg_in.hit_dist - a_hit->hit.hit_dist);
00491                 if ( delta < tol->dist) {
00492                         set_outpoint(seg_p, a_hit);
00493                         ret_val = 2;
00494                         break;
00495                 }
00496                 /* complete the segment */
00497                 BU_LIST_MAGIC_SET( &( (*seg_p)->l ), RT_SEG_MAGIC);
00498                 BU_LIST_INSERT(&(seghead->l), &((*seg_p)->l) );
00499                 (*seg_count)++;
00500 
00501                 /* start new segment */
00502                 (*seg_p) = (struct seg *)NULL;
00503                 set_inpoint(seg_p, a_hit, stp, ap);
00504                 set_outpoint(seg_p, a_hit);
00505 
00506                 ret_val = 4;
00507                 break;
00508         default:
00509                 bu_log("%s[line:%d]: bogus hit in/out status\n",
00510                         __FILE__, __LINE__);
00511                 nmg_rt_segs_exit("Goodbye\n");
00512                 break;
00513         }
00514 
00515         return ret_val;
00516 }
00517 
00518 static int
00519 state3(struct seg *seghead, struct seg **seg_p, int *seg_count, struct hitmiss *a_hit, struct soltab *stp, struct application *ap, struct bn_tol *tol)
00520                                 /* intersection w/ ray */
00521                                 /* The segment we're building */
00522                                 /* The number of valid segments built */
00523                                 /* The input hit point */
00524 
00525 
00526 
00527 {
00528         int ret_val = -1;
00529         double delta;
00530 
00531         CK_SEGP(seg_p);
00532         BN_CK_TOL(tol);
00533         delta = fabs((*seg_p)->seg_in.hit_dist - a_hit->hit.hit_dist);
00534 
00535         switch (a_hit->in_out) {
00536         case HMG_HIT_OUT_ON:
00537         case HMG_HIT_OUT_IN:
00538                 if ( delta < tol->dist) {
00539                         ret_val = 5;
00540                 } else {
00541                         /* complete the segment */
00542                         BU_LIST_MAGIC_SET( &( (*seg_p)->l ), RT_SEG_MAGIC);
00543                         BU_LIST_INSERT(&(seghead->l), &((*seg_p)->l) );
00544                         (*seg_count)++;
00545 
00546                         /* start new segment */
00547                         (*seg_p) = (struct seg *)NULL;
00548                         set_inpoint(seg_p, a_hit, stp, ap);
00549 
00550                         ret_val = 1;
00551                 }
00552                 break;
00553         case HMG_HIT_IN_IN:
00554         case HMG_HIT_ON_IN:
00555         case HMG_HIT_IN_ON:
00556         case HMG_HIT_ON_ON:
00557                 if ( delta < tol->dist) {
00558                         ret_val = 3;
00559                 } else {
00560                         /* Error */
00561                         bu_log("%s[line:%d]: State transition error.\n",
00562                                 __FILE__, __LINE__);
00563                         ret_val = -2;
00564                 }
00565                 break;
00566         case HMG_HIT_ON_OUT:
00567         case HMG_HIT_IN_OUT:
00568                 /*
00569                  * This can happen when the ray hits an edge/vertex and
00570                  * (due to floating point fuzz) also appears to have a
00571                  * hit point in the area of a face:
00572                  *
00573                  * ------->o
00574                  *        / \------------>
00575                  *       /   \
00576                  *
00577                  */
00578                 set_outpoint(seg_p, a_hit);
00579                 ret_val = 2;
00580                 break;
00581         case HMG_HIT_OUT_OUT:
00582                 if (delta > tol->dist) {
00583                         /* complete the segment */
00584                         BU_LIST_MAGIC_SET( &( (*seg_p)->l ), RT_SEG_MAGIC);
00585                         BU_LIST_INSERT(&(seghead->l), &((*seg_p)->l) );
00586                         (*seg_count)++;
00587 
00588                         /* start new segment */
00589                         (*seg_p) = (struct seg *)NULL;
00590                         set_inpoint(seg_p, a_hit, stp, ap);
00591                         set_outpoint(seg_p, a_hit);
00592                 }
00593                 ret_val = 3;
00594                 break;
00595         case HMG_HIT_ANY_ANY:
00596                 if (delta < tol->dist) {
00597                         ret_val = 3;
00598                 } else {
00599                         /* complete the segment */
00600                         BU_LIST_MAGIC_SET( &( (*seg_p)->l ), RT_SEG_MAGIC);
00601                         BU_LIST_INSERT(&(seghead->l), &((*seg_p)->l) );
00602                         (*seg_count)++;
00603 
00604                         /* start new segment */
00605                         (*seg_p) = (struct seg *)NULL;
00606                         set_inpoint(seg_p, a_hit, stp, ap);
00607                         ret_val = 4;
00608                 }
00609                 break;
00610         default:
00611                 bu_log("%s[line:%d]: bogus hit in/out status\n",
00612                         __FILE__, __LINE__);
00613                 nmg_rt_segs_exit("Goodbye\n");
00614                 break;
00615         }
00616 
00617         return ret_val;
00618 }
00619 
00620 static int
00621 state4(struct seg *seghead, struct seg **seg_p, int *seg_count, struct hitmiss *a_hit, struct soltab *stp, struct application *ap, struct bn_tol *tol)
00622                                 /* intersection w/ ray */
00623                                 /* The segment we're building */
00624                                 /* The number of valid segments built */
00625                                 /* The input hit point */
00626 
00627 
00628 
00629 {
00630         int ret_val = -1;
00631         double delta;
00632 
00633         switch (a_hit->in_out) {
00634         case HMG_HIT_OUT_ON:
00635         case HMG_HIT_OUT_IN:
00636                 CK_SEGP(seg_p);
00637                 BN_CK_TOL(tol);
00638                 delta = fabs((*seg_p)->seg_in.hit_dist - a_hit->hit.hit_dist);
00639                 if (delta > tol->dist) {
00640                         /* complete the segment */
00641                         BU_LIST_MAGIC_SET( &( (*seg_p)->l ), RT_SEG_MAGIC);
00642                         BU_LIST_INSERT(&(seghead->l), &((*seg_p)->l) );
00643                         (*seg_count)++;
00644 
00645                         /* start new segment */
00646                         (*seg_p) = (struct seg *)NULL;
00647                         set_inpoint(seg_p, a_hit, stp, ap);
00648                 }
00649                 ret_val = 1;
00650                 break;
00651         case HMG_HIT_IN_IN:
00652         case HMG_HIT_ON_IN:
00653         case HMG_HIT_IN_ON:
00654         case HMG_HIT_ON_ON:
00655         case HMG_HIT_ON_OUT:
00656         case HMG_HIT_IN_OUT:
00657                 /* Error */
00658                 bu_log("%s[line:%d]: State transition error.\n",
00659                         __FILE__, __LINE__);
00660                 ret_val = -2;
00661                 break;
00662         case HMG_HIT_OUT_OUT:
00663                 CK_SEGP(seg_p);
00664                 BN_CK_TOL(tol);
00665                 delta = fabs((*seg_p)->seg_in.hit_dist - a_hit->hit.hit_dist);
00666                 if (delta > tol->dist) {
00667                         /* complete the segment */
00668                         BU_LIST_MAGIC_SET( &( (*seg_p)->l ), RT_SEG_MAGIC);
00669                         BU_LIST_INSERT(&(seghead->l), &((*seg_p)->l) );
00670                         (*seg_count)++;
00671 
00672                         /* start new segment */
00673                         (*seg_p) = (struct seg *)NULL;
00674                         set_inpoint(seg_p, a_hit, stp, ap);
00675                         set_outpoint(seg_p, a_hit);
00676                 }
00677                 ret_val = 3;
00678                 break;
00679         case HMG_HIT_ANY_ANY:
00680                 CK_SEGP(seg_p);
00681                 BN_CK_TOL(tol);
00682                 delta = fabs((*seg_p)->seg_in.hit_dist - a_hit->hit.hit_dist);
00683                 if (delta > tol->dist) {
00684                         /* complete the segment */
00685                         BU_LIST_MAGIC_SET( &( (*seg_p)->l ), RT_SEG_MAGIC);
00686                         BU_LIST_INSERT(&(seghead->l), &((*seg_p)->l) );
00687                         (*seg_count)++;
00688 
00689                         /* start new segment */
00690                         (*seg_p) = (struct seg *)NULL;
00691                         set_inpoint(seg_p, a_hit, stp, ap);
00692                         set_outpoint(seg_p, a_hit);
00693                 }
00694                 ret_val = 4;
00695                 break;
00696         default:
00697                 bu_log("%s[line:%d]: bogus hit in/out status\n",
00698                         __FILE__, __LINE__);
00699                 nmg_rt_segs_exit("Goodbye\n");
00700                 break;
00701         }
00702 
00703         return ret_val;
00704 }
00705 
00706 static int
00707 state5(struct seg *seghead, struct seg **seg_p, int *seg_count, struct hitmiss *a_hit, struct soltab *stp, struct application *ap, struct bn_tol *tol)
00708                                 /* intersection w/ ray */
00709                                 /* The segment we're building */
00710                                 /* The number of valid segments built */
00711                                 /* The input hit point */
00712 
00713 
00714 
00715 {
00716         int ret_val = -1;
00717         double delta;
00718 
00719         switch (a_hit->in_out) {
00720         case HMG_HIT_OUT_ON:
00721         case HMG_HIT_OUT_IN:
00722                 CK_SEGP(seg_p);
00723                 BN_CK_TOL(tol);
00724                 delta = fabs((*seg_p)->seg_in.hit_dist - a_hit->hit.hit_dist);
00725                 if (delta < tol->dist) {
00726                         ret_val = 5;
00727                 } else {
00728                         /* complete the segment */
00729                         BU_LIST_MAGIC_SET( &( (*seg_p)->l ), RT_SEG_MAGIC);
00730                         BU_LIST_INSERT(&(seghead->l), &((*seg_p)->l) );
00731                         (*seg_count)++;
00732 
00733                         /* start new segment */
00734                         (*seg_p) = (struct seg *)NULL;
00735                         set_inpoint(seg_p, a_hit, stp, ap);
00736                         ret_val = 1;
00737                 }
00738                 break;
00739         case HMG_HIT_IN_IN:
00740         case HMG_HIT_ON_IN:
00741         case HMG_HIT_IN_ON:
00742         case HMG_HIT_ON_ON:
00743                 ret_val = 1;
00744                 break;
00745         case HMG_HIT_ON_OUT:
00746         case HMG_HIT_IN_OUT:
00747                 set_outpoint(seg_p, a_hit);
00748                 ret_val = 2;
00749                 break;
00750         case HMG_HIT_OUT_OUT:
00751                 CK_SEGP(seg_p);
00752                 BN_CK_TOL(tol);
00753                 delta = fabs((*seg_p)->seg_in.hit_dist - a_hit->hit.hit_dist);
00754                 if (delta < tol->dist) {
00755                         ret_val = 6;
00756                 } else {
00757                         /* complete the segment */
00758                         BU_LIST_MAGIC_SET( &( (*seg_p)->l ), RT_SEG_MAGIC);
00759                         BU_LIST_INSERT(&(seghead->l), &((*seg_p)->l) );
00760                         (*seg_count)++;
00761 
00762                         /* start new segment */
00763                         (*seg_p) = (struct seg *)NULL;
00764                         set_inpoint(seg_p, a_hit, stp, ap);
00765                         set_outpoint(seg_p, a_hit);
00766                         ret_val = 3;
00767                 }
00768                 break;
00769         case HMG_HIT_ANY_ANY:
00770                 CK_SEGP(seg_p);
00771                 BN_CK_TOL(tol);
00772                 delta = fabs((*seg_p)->seg_in.hit_dist - a_hit->hit.hit_dist);
00773                 if (delta < tol->dist) {
00774                         ret_val = 5;
00775                 } else {
00776                         /* complete the segment */
00777                         BU_LIST_MAGIC_SET( &( (*seg_p)->l ), RT_SEG_MAGIC);
00778                         BU_LIST_INSERT(&(seghead->l), &((*seg_p)->l) );
00779                         (*seg_count)++;
00780 
00781                         /* start new segment */
00782                         (*seg_p) = (struct seg *)NULL;
00783                         set_inpoint(seg_p, a_hit, stp, ap);
00784                         set_outpoint(seg_p, a_hit);
00785                         ret_val = 4;
00786                 }
00787                 break;
00788         default:
00789                 bu_log("%s[line:%d]: bogus hit in/out status\n",
00790                         __FILE__, __LINE__);
00791                 nmg_rt_segs_exit("Goodbye\n");
00792                 break;
00793         }
00794 
00795         return ret_val;
00796 }
00797 
00798 static int
00799 state6(struct seg *seghead, struct seg **seg_p, int *seg_count, struct hitmiss *a_hit, struct soltab *stp, struct application *ap, struct bn_tol *tol)
00800                                 /* intersection w/ ray */
00801                                 /* The segment we're building */
00802                                 /* The number of valid segments built */
00803                                 /* The input hit point */
00804 
00805 
00806 
00807 {
00808         int ret_val = -1;
00809         double delta;
00810 
00811         switch (a_hit->in_out) {
00812         case HMG_HIT_OUT_ON:
00813         case HMG_HIT_OUT_IN:
00814                 CK_SEGP(seg_p);
00815                 BN_CK_TOL(tol);
00816                 delta = fabs((*seg_p)->seg_in.hit_dist - a_hit->hit.hit_dist);
00817                 if (delta < tol->dist) {
00818                         ret_val = 5;
00819                 } else {
00820                         /* complete the segment */
00821                         BU_LIST_MAGIC_SET( &( (*seg_p)->l ), RT_SEG_MAGIC);
00822                         BU_LIST_INSERT(&(seghead->l), &((*seg_p)->l) );
00823                         (*seg_count)++;
00824 
00825                         /* start new segment */
00826                         (*seg_p) = (struct seg *)NULL;
00827                         set_inpoint(seg_p, a_hit, stp, ap);
00828                         ret_val = 1;
00829                 }
00830                 break;
00831         case HMG_HIT_IN_IN:
00832         case HMG_HIT_ON_IN:
00833         case HMG_HIT_IN_ON:
00834         case HMG_HIT_ON_ON:
00835                 ret_val = 1;
00836                 break;
00837         case HMG_HIT_ON_OUT:
00838         case HMG_HIT_IN_OUT:
00839                 set_outpoint(seg_p, a_hit);
00840                 ret_val = 2;
00841                 break;
00842         case HMG_HIT_OUT_OUT:
00843                 CK_SEGP(seg_p);
00844                 BN_CK_TOL(tol);
00845                 delta = fabs((*seg_p)->seg_in.hit_dist - a_hit->hit.hit_dist);
00846                 if (delta < tol->dist) {
00847                         ret_val = 6;
00848                 } else {
00849                         /* complete the segment */
00850                         BU_LIST_MAGIC_SET( &( (*seg_p)->l ), RT_SEG_MAGIC);
00851                         BU_LIST_INSERT(&(seghead->l), &((*seg_p)->l) );
00852                         (*seg_count)++;
00853 
00854                         /* start new segment */
00855                         (*seg_p) = (struct seg *)NULL;
00856                         set_inpoint(seg_p, a_hit, stp, ap);
00857                         set_outpoint(seg_p, a_hit);
00858                         ret_val = 3;
00859                 }
00860                 break;
00861         case HMG_HIT_ANY_ANY:
00862                 CK_SEGP(seg_p);
00863                 BN_CK_TOL(tol);
00864                 delta = fabs((*seg_p)->seg_in.hit_dist - a_hit->hit.hit_dist);
00865                 if (delta < tol->dist) {
00866                         ret_val = 6;
00867                 } else {
00868                         /* complete the segment */
00869                         BU_LIST_MAGIC_SET( &( (*seg_p)->l ), RT_SEG_MAGIC);
00870                         BU_LIST_INSERT(&(seghead->l), &((*seg_p)->l) );
00871                         (*seg_count)++;
00872 
00873                         /* start new segment */
00874                         (*seg_p) = (struct seg *)NULL;
00875                         set_inpoint(seg_p, a_hit, stp, ap);
00876                         set_outpoint(seg_p, a_hit);
00877                         ret_val = 4;
00878                 }
00879                 break;
00880         default:
00881                 bu_log("%s[line:%d]: bogus hit in/out status\n",
00882                         __FILE__, __LINE__);
00883                 nmg_rt_segs_exit("Goodbye\n");
00884                 break;
00885         }
00886 
00887         return ret_val;
00888 }
00889 
00890 
00891 static int (*state_table[7])() = {
00892         state0, state1, state2, state3,
00893         state4, state5, state6
00894 };
00895 
00896 
00897 static int
00898 nmg_bsegs(struct ray_data *rd, struct application *ap, struct seg *seghead, struct soltab *stp)
00899 
00900 
00901                                         /* intersection w/ ray */
00902 
00903 {
00904         int ray_state = 0;
00905         int new_state;
00906         struct hitmiss *a_hit = (struct hitmiss *)NULL;
00907         struct hitmiss *hm = (struct hitmiss *)NULL;
00908         struct seg *seg_p = (struct seg *)NULL;
00909         int seg_count = 0;
00910 
00911 #ifndef FAST_NMG
00912         NMG_CK_HITMISS_LISTS(a_hit, rd);
00913 #endif
00914 
00915         for (BU_LIST_FOR(a_hit, hitmiss, &rd->rd_hit)) {
00916 #ifndef FAST_NMG
00917                 NMG_CK_HITMISS(a_hit);
00918 #endif
00919 
00920                 new_state = state_table[ray_state](seghead, &seg_p,
00921                                                         &seg_count, a_hit,
00922                                                         stp, ap, rd->tol);
00923                 if (new_state < 0) {
00924                         /* state transition error.  Print out the hit list
00925                          * and indicate where we were in processing it.
00926                          */
00927                         for (BU_LIST_FOR(hm, hitmiss, &rd->rd_hit)) {
00928                                 if (hm == a_hit) {
00929                                         bu_log("======= State %d ======\n",
00930                                                 ray_state);
00931                                         nmg_rt_print_hitmiss(hm);
00932                                         bu_log("================\n");
00933                                 } else
00934                                         nmg_rt_print_hitmiss(hm);
00935                         }
00936 
00937                         /* Now bomb off */
00938                         bu_log("Primitive: %s, pixel=%d %d, lvl=%d %s\n",
00939                                 rd->stp->st_dp->d_namep,
00940                                 rd->ap->a_x, rd->ap->a_y, rd->ap->a_level,
00941                                 rd->ap->a_purpose );
00942                         bu_log("Ray: pt:(%g %g %g) dir:(%g %g %g)\n",
00943                                 V3ARGS(rd->rp->r_pt), V3ARGS(rd->rp->r_dir) );
00944                         nmg_rt_segs_exit("Goodbye\n");
00945                 }
00946 
00947                 ray_state = new_state;
00948         }
00949 
00950         /* Check to make sure the input ran out in the right place
00951          * in the state table.
00952          */
00953         if (ray_state == 1) {
00954                 bu_log("%s[line:%d]: Input ended at non-terminal FSM state\n",
00955                         __FILE__, __LINE__);
00956 
00957                 bu_log("Ray: pt:(%g %g %g) dir:(%g %g %g)\n",
00958                         V3ARGS(rd->rp->r_pt), V3ARGS(rd->rp->r_dir) );
00959 
00960                 bu_log("Primitive: %s, pixel=%d %d, lvl=%d %s\n",
00961                         stp->st_dp->d_namep,
00962                         ap->a_x, ap->a_y, ap->a_level,
00963                         ap->a_purpose );
00964                 nmg_rt_segs_exit("Goodbye");
00965         }
00966 
00967         /* Insert the last segment if appropriate */
00968         if (ray_state > 1) {
00969                 /* complete the segment */
00970                 BU_LIST_MAGIC_SET( &( seg_p->l ), RT_SEG_MAGIC);
00971                 BU_LIST_INSERT(&(seghead->l), &(seg_p->l) );
00972                 seg_count++;
00973         }
00974 
00975         return seg_count;
00976 }
00977 
00978 /**
00979  *      If a_tbl and next_tbl have an element in common, return it.
00980  *      Otherwise return a NULL pointer.
00981  */
00982 static long *
00983 common_topo(struct bu_ptbl *a_tbl, struct bu_ptbl *next_tbl)
00984 {
00985         long **p;
00986 
00987         for (p = &a_tbl->buffer[a_tbl->end] ; p >= a_tbl->buffer ; p--) {
00988                 if (bu_ptbl_locate(next_tbl, *p) >= 0)
00989                         return *p;
00990         }
00991 
00992         return (long *)NULL;
00993 }
00994 
00995 
00996 static void
00997 visitor(long int *l_p, genptr_t tbl, int after)
00998 {
00999         (void)bu_ptbl_ins_unique( (struct bu_ptbl *)tbl, l_p);
01000 }
01001 
01002 /**
01003  *      Add an element provided by nmg_visit to a bu_ptbl struct.
01004  */
01005 static void
01006 build_topo_list(long int *l_p, struct bu_ptbl *tbl)
01007 {
01008         struct loopuse *lu;
01009         struct edgeuse *eu;
01010         struct edgeuse *eu_p;
01011         struct vertexuse *vu;
01012         struct vertexuse *vu_p;
01013         int radial_not_mate=0;
01014         static const struct nmg_visit_handlers htab = {NULL, NULL, NULL, NULL, NULL,
01015                                                        NULL, NULL, NULL, NULL, NULL,
01016                                                        visitor, NULL, NULL, NULL, NULL,
01017                                                        NULL, NULL, NULL, visitor, NULL,
01018                                                        NULL, NULL, NULL, visitor, NULL};
01019         /* htab.vis_face = htab.vis_edge = htab.vis_vertex = visitor; */
01020 
01021         if (!l_p) {
01022                 bu_log("%s:%d NULL l_p\n", __FILE__, __LINE__);
01023                 nmg_rt_segs_exit("");
01024         }
01025 
01026         switch (*l_p) {
01027         case NMG_FACEUSE_MAGIC:
01028                 nmg_visit(l_p, &htab, (genptr_t)tbl);
01029                 break;
01030         case NMG_EDGEUSE_MAGIC:
01031                 eu = eu_p = (struct edgeuse *)l_p;
01032                 do {
01033                         /* if the parent of this edgeuse is a face loopuse
01034                          * add the face to the list of shared topology
01035                          */
01036                         if (*eu->up.magic_p == NMG_LOOPUSE_MAGIC &&
01037                             *eu->up.lu_p->up.magic_p == NMG_FACEUSE_MAGIC)
01038                                 bu_ptbl_ins_unique(tbl,
01039                                         (long *)eu->up.lu_p->up.fu_p->f_p);
01040 
01041                         if (radial_not_mate)    eu = eu->radial_p;
01042                         else                    eu = eu->eumate_p;
01043                         radial_not_mate = ! radial_not_mate;
01044                 } while (eu != eu_p);
01045 
01046                 bu_ptbl_ins_unique(tbl, (long *)eu->e_p);
01047                 bu_ptbl_ins_unique(tbl, (long *)eu->vu_p->v_p);
01048                 bu_ptbl_ins_unique(tbl, (long *)eu->eumate_p->vu_p->v_p);
01049 
01050                 break;
01051         case NMG_VERTEXUSE_MAGIC:
01052                 vu_p = (struct vertexuse *)l_p;
01053                 bu_ptbl_ins_unique(tbl, (long *)vu_p->v_p);
01054 
01055                 for (BU_LIST_FOR(vu, vertexuse, &vu_p->v_p->vu_hd)) {
01056                         lu = (struct loopuse *)NULL;
01057                         switch (*vu->up.magic_p) {
01058                         case NMG_EDGEUSE_MAGIC:
01059                                 eu = vu->up.eu_p;
01060                                 bu_ptbl_ins_unique(tbl, (long *)eu->e_p);
01061                                 if (*eu->up.magic_p !=  NMG_LOOPUSE_MAGIC)
01062                                         break;
01063 
01064                                 lu = eu->up.lu_p;
01065                                 /* fallthrough */
01066 
01067                         case NMG_LOOPUSE_MAGIC:
01068                                 if ( ! lu ) lu = vu->up.lu_p;
01069 
01070                                 if (*lu->up.magic_p == NMG_FACEUSE_MAGIC)
01071                                         bu_ptbl_ins_unique(tbl,
01072                                                 (long *)lu->up.fu_p->f_p);
01073                                 break;
01074                         case NMG_SHELL_MAGIC:
01075                                 break;
01076                         default:
01077                                 bu_log("%s[%d]: Bogus vertexuse parent magic:%s.",
01078                                         bu_identify_magic( *vu->up.magic_p ));
01079                                 nmg_rt_segs_exit("goodbye");
01080                         }
01081                 }
01082                 break;
01083         default:
01084                 bu_log("%s[%d]: Bogus magic number pointer:%s",
01085                         bu_identify_magic( *l_p ) );
01086                 nmg_rt_segs_exit("goodbye");
01087         }
01088 }
01089 
01090 static void
01091 unresolved(struct hitmiss *a_hit, struct hitmiss *next_hit, struct bu_ptbl *a_tbl, struct bu_ptbl *next_tbl, struct hitmiss *hd, struct ray_data *rd)
01092 {
01093 
01094         struct hitmiss *hm;
01095         register long **l_p;
01096         register long **b;
01097 
01098         bu_log("Unable to fix state transition--->\n");
01099         bu_log( "\tray start = (%f %f %f) dir = (%f %f %f)\n",
01100                 V3ARGS( rd->rp->r_pt ), V3ARGS( rd->rp->r_dir ) );
01101         for (BU_LIST_FOR(hm, hitmiss, &hd->l)) {
01102                 if (hm == next_hit) {
01103                         bu_log("======= ======\n");
01104                         nmg_rt_print_hitmiss(hm);
01105                         bu_log("================\n");
01106                 } else
01107                         nmg_rt_print_hitmiss(hm);
01108         }
01109 
01110         bu_log("topo table A\n");
01111         b = &a_tbl->buffer[a_tbl->end];
01112         l_p = &a_tbl->buffer[0];
01113         for ( ; l_p < b ; l_p ++)
01114                 bu_log("\t0x%08x %s\n",**l_p, bu_identify_magic( **l_p));
01115 
01116         bu_log("topo table NEXT\n");
01117         b = &next_tbl->buffer[next_tbl->end];
01118         l_p = &next_tbl->buffer[0];
01119         for ( ; l_p < b ; l_p ++)
01120                 bu_log("\t0x%08x %s\n",**l_p, bu_identify_magic( **l_p));
01121 
01122         bu_log("<---Unable to fix state transition\n");
01123         pl_ray(rd);
01124         bu_log("Primitive: %s, pixel=%d %d,  lvl=%d %s\n",
01125                 rd->stp->st_dp->d_namep,
01126                 rd->ap->a_x, rd->ap->a_y, rd->ap->a_level,
01127                 rd->ap->a_purpose );
01128 }
01129 
01130 
01131 static int
01132 check_hitstate(struct hitmiss *hd, struct ray_data *rd)
01133 {
01134         struct hitmiss *a_hit;
01135         struct hitmiss *next_hit;
01136         int ibs;
01137         int obs;
01138         struct bu_ptbl *a_tbl = (struct bu_ptbl *)NULL;
01139         struct bu_ptbl *next_tbl = (struct bu_ptbl *)NULL;
01140         struct bu_ptbl *tbl_p = (struct bu_ptbl *)NULL;
01141         long *long_ptr;
01142 
01143         BU_CK_LIST_HEAD(&hd->l);
01144 
01145 #ifndef FAST_NMG
01146         NMG_CK_HITMISS_LISTS(a_hit, rd);
01147 #endif
01148 
01149         /* find that first "OUTSIDE" point */
01150         a_hit = BU_LIST_FIRST(hitmiss, &hd->l);
01151 #ifndef FAST_NMG
01152         NMG_CK_HITMISS(a_hit);
01153 #endif
01154         if (((a_hit->in_out & 0x0f0) >> 4) != NMG_RAY_STATE_OUTSIDE ||
01155             rt_g.NMG_debug & DEBUG_RT_SEGS) {
01156                 bu_log("check_hitstate()\n");
01157                 nmg_rt_print_hitlist(hd);
01158 
01159                 bu_log("Ray: pt:(%g %g %g) dir:(%g %g %g)\n",
01160                         V3ARGS(rd->rp->r_pt), V3ARGS(rd->rp->r_dir) );
01161         }
01162 
01163         while( a_hit != hd &&
01164                 ((a_hit->in_out & 0x0f0) >> 4) != NMG_RAY_STATE_OUTSIDE) {
01165 
01166 
01167 #ifndef FAST_NMG
01168                 NMG_CK_HITMISS(a_hit);
01169 #endif
01170                 /* this better be a 2-manifold face */
01171                 bu_log("%s[%d]: This better be a 2-manifold face\n",
01172                         __FILE__, __LINE__);
01173                 bu_log("Primitive: %s, pixel=%d %d,  lvl=%d %s\n",
01174                                 rd->stp->st_dp->d_namep,
01175                                 rd->ap->a_x, rd->ap->a_y, rd->ap->a_level,
01176                                 rd->ap->a_purpose );
01177                 a_hit = BU_LIST_PNEXT(hitmiss, a_hit);
01178                 if (a_hit != hd) {
01179 #ifndef FAST_NMG
01180                         NMG_CK_HITMISS(a_hit);
01181 #endif
01182                 }
01183         }
01184         if (a_hit == hd) return 1;
01185 
01186         a_tbl = (struct bu_ptbl *)
01187                 bu_calloc(1, sizeof(struct bu_ptbl), "a_tbl");
01188         bu_ptbl_init(a_tbl, 64, "a_tbl");
01189 
01190 
01191         next_tbl = (struct bu_ptbl *)
01192                 bu_calloc(1, sizeof(struct bu_ptbl), "next_tbl");
01193         bu_ptbl_init(next_tbl, 64, "next_tbl");
01194 
01195         /* check the state transition on the rest of the hit points */
01196         while ((next_hit = BU_LIST_PNEXT(hitmiss, &a_hit->l)) != hd) {
01197 #ifndef FAST_NMG
01198                 NMG_CK_HITMISS(next_hit);
01199 #endif
01200                 ibs = HMG_INBOUND_STATE(next_hit);
01201                 obs = HMG_OUTBOUND_STATE(a_hit);
01202                 if (ibs != obs) {
01203                         /* if these two hits share some common topological
01204                          * element, then we can fix things.
01205                          *
01206                          * First we build the table of elements associated
01207                          * with each hit.
01208                          */
01209 
01210                         bu_ptbl_reset(a_tbl);
01211 
01212 #ifndef FAST_NMG
01213                         NMG_CK_HITMISS(a_hit);
01214 #endif
01215                         build_topo_list(a_hit->outbound_use, a_tbl);
01216 
01217                         bu_ptbl_reset(next_tbl);
01218 #ifndef FAST_NMG
01219                         NMG_CK_HITMISS(next_hit);
01220 #endif
01221                         build_topo_list(next_hit->outbound_use, next_tbl);
01222 
01223 
01224                         /* If the tables have elements in common,
01225                          *   then resolve the conflict by
01226                          *      morphing the two hits to match.
01227                          *   else
01228                          *      This is a real conflict.
01229                          */
01230                         if ( (long_ptr = common_topo(a_tbl, next_tbl)) ) {
01231                                 /* morf the two hit points */
01232                                 a_hit->in_out = (a_hit->in_out & 0x0f0) +
01233                                         NMG_RAY_STATE_ON;
01234                                 a_hit->outbound_use = long_ptr;
01235 
01236                                 next_hit->in_out = (next_hit->in_out & 0x0f) +
01237                                         (NMG_RAY_STATE_ON << 4);
01238                                 a_hit->inbound_use = long_ptr;
01239 
01240                         } else
01241                                 unresolved(a_hit, next_hit,
01242                                                 a_tbl, next_tbl, hd, rd);
01243 
01244                 }
01245 
01246                 /* save next_tbl as a_tbl for next iteration */
01247                 tbl_p = a_tbl;
01248                 a_tbl = next_tbl;
01249                 next_tbl = tbl_p;
01250 
01251                 a_hit = next_hit;
01252         }
01253 
01254         bu_ptbl_free(next_tbl);
01255         bu_ptbl_free(a_tbl);
01256         (void)bu_free( (char *)a_tbl, "a_tbl");
01257         (void)bu_free( (char *)next_tbl, "next_tbl");
01258 
01259         return 0;
01260 }
01261 
01262 /**     N M G _ R A Y _ S E G S
01263  *
01264  *      Obtain the list of ray segments which intersect with the nmg.
01265  *      This routine does all of the "work" for rt_nmg_shot()
01266  *
01267  *      Return:
01268  *              # of segments added to list.
01269  */
01270 int
01271 nmg_ray_segs(struct ray_data *rd)
01272 {
01273         struct hitmiss *a_hit;
01274         static int last_miss=0;
01275 
01276 #ifdef DO_LONGJMP
01277         if (setjmp(nmg_longjump_env) != 0) {
01278                 return 0;
01279         }
01280 #endif
01281 
01282 #ifndef FAST_NMG
01283         NMG_CK_HITMISS_LISTS(a_hit, rd);
01284 #endif
01285 
01286         if (BU_LIST_IS_EMPTY(&rd->rd_hit)) {
01287 
01288                 NMG_FREE_HITLIST( &rd->rd_miss, rd->ap );
01289 
01290                 if (rt_g.NMG_debug & DEBUG_RT_SEGS) {
01291                         if (last_miss)  bu_log(".");
01292                         else            bu_log("ray missed NMG\n");
01293                 }
01294                 last_miss = 1;
01295                 return(0);                      /* MISS */
01296         } else if (rt_g.NMG_debug & DEBUG_RT_SEGS) {
01297                 int seg_count=0;
01298 
01299                 print_seg_list(rd->seghead, seg_count, "before");
01300 
01301                 bu_log("\n\nnmg_ray_segs(rd)\nsorted nmg/ray hit list\n");
01302 
01303                 for (BU_LIST_FOR(a_hit, hitmiss, &rd->rd_hit))
01304                         nmg_rt_print_hitmiss(a_hit);
01305         }
01306 
01307         last_miss = 0;
01308 
01309         if (check_hitstate((struct hitmiss *)&rd->rd_hit, rd)) {
01310                 NMG_FREE_HITLIST( &rd->rd_hit, rd->ap );
01311                 NMG_FREE_HITLIST( &rd->rd_miss, rd->ap );
01312                 return 0;
01313         }
01314 
01315         if (rt_g.NMG_debug & DEBUG_RT_SEGS) {
01316                 bu_log("----------morphed nmg/ray hit list---------\n");
01317                 for (BU_LIST_FOR(a_hit, hitmiss, &rd->rd_hit))
01318                         nmg_rt_print_hitmiss(a_hit);
01319 
01320                 pl_ray(rd);
01321         }
01322 
01323         {
01324                 int seg_count = nmg_bsegs(rd, rd->ap, rd->seghead, rd->stp);
01325 
01326 
01327                 NMG_FREE_HITLIST( &rd->rd_hit, rd->ap );
01328                 NMG_FREE_HITLIST( &rd->rd_miss, rd->ap );
01329 
01330 
01331                 if (rt_g.NMG_debug & DEBUG_RT_SEGS) {
01332                         /* print debugging data before returning */
01333                         print_seg_list(rd->seghead, seg_count, "after");
01334                 }
01335                 return(seg_count);
01336         }
01337 }
01338 
01339 
01340 /*
01341  * Local Variables:
01342  * mode: C
01343  * tab-width: 8
01344  * c-basic-offset: 4
01345  * indent-tabs-mode: t
01346  * End:
01347  * ex: shiftwidth=4 tabstop=8
01348  */

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