00001
00002
00003
00004
00005
00006
00007
00008
00009
00010
00011
00012
00013
00014
00015
00016
00017
00018
00019
00020
00021
00022
00023
00024
00025
00026
00027
00028
00029
00030
00031
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
00055
00056
00057 struct ef_data {
00058 fastf_t fdotr;
00059 fastf_t fdotl;
00060 fastf_t ndotr;
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
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
00212
00213
00214
00215
00216
00217
00218
00219
00220
00221
00222
00223
00224
00225
00226
00227
00228
00229
00230
00231
00232
00233
00234
00235
00236
00237
00238
00239
00240
00241
00242
00243
00244
00245
00246
00247
00248 static void
00249 set_inpoint(struct seg **seg_p, struct hitmiss *a_hit, struct soltab *stp, struct application *ap)
00250
00251
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
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
00268 bcopy(&a_hit->hit, &(*seg_p)->seg_in, sizeof(struct hit));
00269
00270
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
00288
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
00297 if ( *seg_p == (struct seg *)NULL )
00298 nmg_rt_segs_exit("bad seg pointer\n");
00299
00300
00301 bcopy(&a_hit->hit, &(*seg_p)->seg_out, sizeof(struct hit));
00302
00303
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
00331
00332
00333
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
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
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
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
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
00383
00384
00385
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
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
00427
00428
00429
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
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
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
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
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
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
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
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
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
00521
00522
00523
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
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
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
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
00570
00571
00572
00573
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
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
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
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
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
00623
00624
00625
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
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
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
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
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
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
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
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
00709
00710
00711
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
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
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
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
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
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
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
00801
00802
00803
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
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
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
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
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
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
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
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
00925
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
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
00951
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
00968 if (ray_state > 1) {
00969
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
00980
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
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
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
01034
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
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
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
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
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
01204
01205
01206
01207
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
01225
01226
01227
01228
01229
01230 if ( (long_ptr = common_topo(a_tbl, next_tbl)) ) {
01231
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
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
01263
01264
01265
01266
01267
01268
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);
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
01333 print_seg_list(rd->seghead, seg_count, "after");
01334 }
01335 return(seg_count);
01336 }
01337 }
01338
01339
01340
01341
01342
01343
01344
01345
01346
01347
01348