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
00036
00037
00038 #ifndef lint
00039 static const char RCSplane[] = "@(#)$Header: /cvsroot/brlcad/brlcad/src/libbn/plane.c,v 14.10 2006/09/04 04:42:40 lbutler Exp $ (BRL)";
00040 #endif
00041
00042 #include "common.h"
00043
00044 #include <stdio.h>
00045 #include <math.h>
00046 #ifdef HAVE_STRING_H
00047 #include <string.h>
00048 #else
00049 #include <strings.h>
00050 #endif
00051
00052 #include "machine.h"
00053 #include "bu.h"
00054 #include "vmath.h"
00055 #include "bn.h"
00056
00057 #define UNIT_SQ_TOL 1.0e-13
00058
00059
00060
00061
00062
00063
00064 double
00065 bn_dist_pt3_pt3(const fastf_t *a, const fastf_t *b)
00066 {
00067 vect_t diff;
00068
00069 VSUB2( diff, a, b );
00070 return MAGNITUDE( diff );
00071 }
00072
00073
00074
00075
00076
00077
00078
00079
00080 int
00081 bn_pt3_pt3_equal(const fastf_t *a, const fastf_t *b, const struct bn_tol *tol)
00082 {
00083 vect_t diff;
00084
00085 BN_CK_TOL(tol);
00086 VSUB2( diff, b, a );
00087 if( MAGSQ( diff ) < tol->dist_sq ) return 1;
00088 return 0;
00089 }
00090
00091
00092
00093
00094
00095
00096
00097
00098 int
00099 bn_pt2_pt2_equal(const fastf_t *a, const fastf_t *b, const struct bn_tol *tol)
00100 {
00101 vect_t diff;
00102
00103 BN_CK_TOL(tol);
00104 VSUB2_2D( diff, b, a );
00105 if( MAGSQ_2D( diff ) < tol->dist_sq ) return 1;
00106 return 0;
00107 }
00108
00109
00110
00111
00112
00113
00114
00115
00116
00117
00118
00119
00120 int
00121 bn_3pts_collinear(fastf_t *a, fastf_t *b, fastf_t *c, const struct bn_tol *tol)
00122 {
00123 fastf_t mag_ab, mag_bc, mag_ca, max_len, dist_sq;
00124 fastf_t cos_a, cos_b, cos_c;
00125 vect_t ab, bc, ca;
00126 int max_edge_no;
00127
00128 VSUB2(ab, b, a);
00129 VSUB2(bc, c, b);
00130 VSUB2(ca, a, c);
00131 mag_ab = MAGNITUDE(ab);
00132 mag_bc = MAGNITUDE(bc);
00133 mag_ca = MAGNITUDE(ca);
00134
00135
00136 max_len = mag_ab;
00137 max_edge_no = 1;
00138
00139 if( mag_bc > max_len )
00140 {
00141 max_len = mag_bc;
00142 max_edge_no = 2;
00143 }
00144
00145 if( mag_ca > max_len )
00146 {
00147 max_len = mag_ca;
00148 max_edge_no = 3;
00149 }
00150
00151 switch( max_edge_no )
00152 {
00153 default:
00154 case 1:
00155 cos_b = (-VDOT( ab , bc ))/(mag_ab * mag_bc );
00156 dist_sq = mag_bc*mag_bc*( 1.0 - cos_b*cos_b);
00157 break;
00158 case 2:
00159 cos_c = (-VDOT( bc , ca ))/(mag_bc * mag_ca );
00160 dist_sq = mag_ca*mag_ca*(1.0 - cos_c*cos_c);
00161 break;
00162 case 3:
00163 cos_a = (-VDOT( ca , ab ))/(mag_ca * mag_ab );
00164 dist_sq = mag_ab*mag_ab*(1.0 - cos_a*cos_a);
00165 break;
00166 }
00167
00168 if( dist_sq <= tol->dist_sq )
00169 return( 1 );
00170 else
00171 return( 0 );
00172 }
00173
00174
00175
00176
00177
00178
00179
00180
00181
00182
00183
00184
00185
00186 int
00187 bn_3pts_distinct(const fastf_t *a, const fastf_t *b, const fastf_t *c, const struct bn_tol *tol)
00188 {
00189 vect_t B_A;
00190 vect_t C_A;
00191 vect_t C_B;
00192
00193 BN_CK_TOL(tol);
00194 VSUB2( B_A, b, a );
00195 if( MAGSQ( B_A ) <= tol->dist_sq ) return(0);
00196 VSUB2( C_A, c, a );
00197 if( MAGSQ( C_A ) <= tol->dist_sq ) return(0);
00198 VSUB2( C_B, c, b );
00199 if( MAGSQ( C_B ) <= tol->dist_sq ) return(0);
00200 return(1);
00201 }
00202
00203
00204
00205
00206
00207
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 int
00247 bn_mk_plane_3pts(fastf_t *plane,
00248 const fastf_t *a,
00249 const fastf_t *b,
00250 const fastf_t *c,
00251 const struct bn_tol *tol)
00252 {
00253 vect_t B_A;
00254 vect_t C_A;
00255 vect_t C_B;
00256 register fastf_t mag;
00257
00258 BN_CK_TOL(tol);
00259
00260 VSUB2( B_A, b, a );
00261 if( MAGSQ( B_A ) <= tol->dist_sq ) return(-1);
00262 VSUB2( C_A, c, a );
00263 if( MAGSQ( C_A ) <= tol->dist_sq ) return(-1);
00264 VSUB2( C_B, c, b );
00265 if( MAGSQ( C_B ) <= tol->dist_sq ) return(-1);
00266
00267 VCROSS( plane, B_A, C_A );
00268
00269
00270 if( (mag = MAGNITUDE(plane)) <= SMALL_FASTF )
00271 return(-1);
00272 mag = 1/mag;
00273 VSCALE( plane, plane, mag );
00274
00275
00276
00277 plane[3] = VDOT( plane, a );
00278
00279 #if 0
00280
00281
00282 mag = MAGSQ(a);
00283 if( mag > tol->dist_sq ) {
00284
00285 if( plane[3]/sqrt(mag) < 0.017452406 ) {
00286 bu_log("bn_mk_plane_3pts() WARNING: plane[3] value is suspect\n");
00287 }
00288 }
00289 #endif
00290 return(0);
00291 }
00292
00293
00294
00295
00296
00297
00298
00299
00300
00301
00302
00303
00304
00305
00306
00307
00308
00309
00310
00311
00312
00313
00314
00315
00316
00317
00318
00319
00320
00321
00322 int
00323 bn_mkpoint_3planes(fastf_t *pt, const fastf_t *a, const fastf_t *b, const fastf_t *c)
00324 {
00325 vect_t v1, v2, v3;
00326 register fastf_t det;
00327
00328
00329 VCROSS( v1, b, c );
00330
00331
00332
00333
00334
00335
00336 det = VDOT( a, v1 );
00337 if( NEAR_ZERO( det, SMALL_FASTF ) ) return(-1);
00338
00339 VCROSS( v2, a, c );
00340 VCROSS( v3, a, b );
00341
00342 det = 1/det;
00343 pt[X] = det*(a[3]*v1[X] - b[3]*v2[X] + c[3]*v3[X]);
00344 pt[Y] = det*(a[3]*v1[Y] - b[3]*v2[Y] + c[3]*v3[Y]);
00345 pt[Z] = det*(a[3]*v1[Z] - b[3]*v2[Z] + c[3]*v3[Z]);
00346 return(0);
00347 }
00348
00349
00350
00351
00352
00353
00354
00355
00356
00357
00358
00359
00360 int
00361 bn_2line3_colinear(const fastf_t *p1,
00362 const fastf_t *d1,
00363 const fastf_t *p2,
00364 const fastf_t *d2,
00365 double range,
00366 const struct bn_tol *tol)
00367 {
00368 fastf_t mag1;
00369 fastf_t mag2;
00370 point_t tail;
00371
00372 BN_CK_TOL(tol);
00373
00374 if( (mag1 = MAGNITUDE(d1)) < SMALL_FASTF ) bu_bomb("bn_2line3_colinear() mag1 zero\n");
00375 if( (mag2 = MAGNITUDE(d2)) < SMALL_FASTF ) bu_bomb("bn_2line3_colinear() mag2 zero\n");
00376
00377
00378
00379 if( fabs(VDOT(d1, d2)) < 0.9 * mag1 * mag2 ) goto fail;
00380
00381
00382 if( bn_distsq_line3_pt3( p1, d1, p2 ) > tol->dist_sq ) goto fail;
00383 if( bn_distsq_line3_pt3( p2, d2, p1 ) > tol->dist_sq ) goto fail;
00384
00385 VJOIN1( tail, p1, range/mag1, d1 );
00386 if( bn_distsq_line3_pt3( p2, d2, tail ) > tol->dist_sq ) goto fail;
00387
00388 VJOIN1( tail, p2, range/mag2, d2 );
00389 if( bn_distsq_line3_pt3( p1, d1, tail ) > tol->dist_sq ) goto fail;
00390
00391 if( bu_debug & BU_DEBUG_MATH ) {
00392 bu_log("bn_2line3colinear(range=%g) ret=1\n",range);
00393 }
00394 return 1;
00395 fail:
00396 if( bu_debug & BU_DEBUG_MATH ) {
00397 bu_log("bn_2line3colinear(range=%g) ret=0\n",range);
00398 }
00399 return 0;
00400 }
00401
00402
00403
00404
00405
00406
00407
00408
00409
00410
00411
00412
00413
00414
00415
00416
00417
00418
00419
00420
00421
00422
00423
00424 int
00425 bn_isect_line3_plane(fastf_t *dist,
00426 const fastf_t *pt,
00427 const fastf_t *dir,
00428 const fastf_t *plane,
00429 const struct bn_tol *tol)
00430 {
00431 register fastf_t slant_factor;
00432 register fastf_t norm_dist;
00433 register fastf_t dot;
00434 vect_t local_dir;
00435
00436 BN_CK_TOL(tol);
00437
00438 norm_dist = plane[3] - VDOT( plane, pt );
00439 slant_factor = VDOT( plane, dir );
00440 VMOVE( local_dir, dir )
00441 VUNITIZE( local_dir )
00442 dot = VDOT( plane, local_dir );
00443
00444 if( slant_factor < -SMALL_FASTF && dot < -tol->perp ) {
00445 *dist = norm_dist/slant_factor;
00446 return 1;
00447 } else if( slant_factor > SMALL_FASTF && dot > tol->perp ) {
00448 *dist = norm_dist/slant_factor;
00449 return 2;
00450 }
00451
00452
00453
00454
00455 *dist = 0;
00456 if( norm_dist < -tol->dist )
00457 return -2;
00458 if( norm_dist > tol->dist )
00459 return -1;
00460 return 0;
00461 }
00462
00463
00464
00465
00466
00467
00468
00469
00470
00471
00472
00473
00474
00475
00476
00477
00478
00479
00480
00481
00482
00483
00484
00485
00486
00487
00488
00489 int
00490 bn_isect_2planes(fastf_t *pt,
00491 fastf_t *dir,
00492 const fastf_t *a,
00493 const fastf_t *b,
00494 const fastf_t *rpp_min,
00495 const struct bn_tol *tol)
00496 {
00497 LOCAL vect_t abs_dir;
00498 LOCAL plane_t pl;
00499 int i;
00500
00501 if( (i = bn_coplanar( a, b, tol )) != 0 ) {
00502 if( i > 0 )
00503 return(-1);
00504 return(-2);
00505 }
00506
00507
00508 VCROSS( dir, a, b );
00509 VUNITIZE( dir );
00510
00511
00512
00513
00514
00515
00516
00517
00518 abs_dir[X] = (dir[X] >= 0) ? dir[X] : (-dir[X]);
00519 abs_dir[Y] = (dir[Y] >= 0) ? dir[Y] : (-dir[Y]);
00520 abs_dir[Z] = (dir[Z] >= 0) ? dir[Z] : (-dir[Z]);
00521
00522 if( abs_dir[X] >= abs_dir[Y] ) {
00523 if( abs_dir[X] >= abs_dir[Z] ) {
00524 VSET( pl, 1, 0, 0 );
00525 pl[3] = rpp_min[X];
00526 if( dir[X] < 0 ) {
00527 VREVERSE( dir, dir );
00528 }
00529 } else {
00530 VSET( pl, 0, 0, 1 );
00531 pl[3] = rpp_min[Z];
00532 if( dir[Z] < 0 ) {
00533 VREVERSE( dir, dir );
00534 }
00535 }
00536 } else {
00537 if( abs_dir[Y] >= abs_dir[Z] ) {
00538 VSET( pl, 0, 1, 0 );
00539 pl[3] = rpp_min[Y];
00540 if( dir[Y] < 0 ) {
00541 VREVERSE( dir, dir );
00542 }
00543 } else {
00544 VSET( pl, 0, 0, 1 );
00545 pl[3] = rpp_min[Z];
00546 if( dir[Z] < 0 ) {
00547 VREVERSE( dir, dir );
00548 }
00549 }
00550 }
00551
00552
00553 if( bn_mkpoint_3planes( pt, pl, a, b ) < 0 )
00554 return(-3);
00555
00556 return(0);
00557 }
00558
00559
00560
00561
00562
00563
00564
00565
00566
00567
00568
00569
00570
00571
00572
00573
00574
00575
00576
00577
00578
00579
00580
00581
00582
00583
00584
00585
00586
00587
00588
00589
00590
00591
00592
00593
00594
00595
00596
00597
00598
00599
00600
00601 int
00602 bn_isect_line2_line2(fastf_t *dist, const fastf_t *p, const fastf_t *d, const fastf_t *a, const fastf_t *c, const struct bn_tol *tol)
00603
00604
00605
00606
00607
00608
00609 {
00610 fastf_t hx, hy;
00611 register fastf_t det;
00612 register fastf_t det1;
00613 vect_t unit_d;
00614 vect_t unit_c;
00615 vect_t unit_h;
00616 int parallel;
00617 int parallel1;
00618
00619 BN_CK_TOL(tol);
00620 if( bu_debug & BU_DEBUG_MATH ) {
00621 bu_log("bn_isect_line2_line2() p=(%g,%g), d=(%g,%g)\n\t\t\ta=(%g,%g), c=(%g,%g)\n",
00622 V2ARGS(p), V2ARGS(d), V2ARGS(a), V2ARGS(c) );
00623 }
00624
00625
00626
00627
00628
00629
00630
00631
00632
00633
00634
00635
00636
00637
00638
00639
00640
00641
00642
00643
00644
00645
00646
00647
00648
00649
00650
00651
00652
00653
00654
00655
00656
00657 det = c[X] * d[Y] - d[X] * c[Y];
00658
00659
00660
00661
00662
00663
00664
00665
00666
00667
00668
00669
00670
00671
00672
00673
00674
00675
00676
00677
00678
00679
00680
00681
00682 hx = a[X] - p[X];
00683 hy = a[Y] - p[Y];
00684 det1 = (c[X] * hy - hx * c[Y]);
00685
00686 unit_d[0] = d[0];
00687 unit_d[1] = d[1];
00688 unit_d[2] = 0.0;
00689 VUNITIZE( unit_d );
00690 unit_c[0] = c[0];
00691 unit_c[1] = c[1];
00692 unit_c[2] = 0.0;
00693 VUNITIZE( unit_c );
00694 unit_h[0] = hx;
00695 unit_h[1] = hy;
00696 unit_h[2] = 0.0;
00697 VUNITIZE( unit_h );
00698
00699 if( fabs( VDOT( unit_d, unit_c ) ) >= tol->para )
00700 parallel = 1;
00701 else
00702 parallel = 0;
00703
00704 if( fabs( VDOT( unit_h, unit_c ) ) >= tol->para )
00705 parallel1 = 1;
00706 else
00707 parallel1 = 0;
00708
00709
00710
00711
00712
00713
00714 #define DETERMINANT_TOL 1.0e-14
00715 if( parallel || NEAR_ZERO( det, DETERMINANT_TOL ) ) {
00716
00717 if( !parallel1 && !NEAR_ZERO( det1, DETERMINANT_TOL ) ) {
00718
00719 if( bu_debug & BU_DEBUG_MATH ) {
00720 bu_log("\tparallel, not co-linear. det=%e, det1=%g\n", det, det1);
00721 }
00722 return -1;
00723 }
00724
00725
00726
00727
00728
00729
00730
00731
00732 if( fabs(d[X]) >= fabs(d[Y]) ) {
00733 dist[0] = hx/d[X];
00734 dist[1] = (hx + c[X]) / d[X];
00735 } else {
00736 dist[0] = hy/d[Y];
00737 dist[1] = (hy + c[Y]) / d[Y];
00738 }
00739 if( bu_debug & BU_DEBUG_MATH ) {
00740 bu_log("\tcolinear, t = %g, u = %g\n", dist[0], dist[1] );
00741 }
00742 return 0;
00743 }
00744 if( bu_debug & BU_DEBUG_MATH ) {
00745
00746 bu_log("\thx=%g, hy=%g, det=%g, det1=%g, det2=%g\n", hx, hy, det, det1, (d[X] * hy - hx * d[Y]) );
00747 }
00748 det = 1/det;
00749 dist[0] = det * det1;
00750 dist[1] = det * (d[X] * hy - hx * d[Y]);
00751 if( bu_debug & BU_DEBUG_MATH ) {
00752 bu_log("\tintersection, t = %g, u = %g\n", dist[0], dist[1] );
00753 }
00754
00755 #if 0
00756
00757
00758
00759
00760
00761
00762
00763 {
00764 point_t hit1, hit2;
00765 vect_t diff;
00766 fastf_t dist_sq;
00767
00768 VJOIN1_2D( hit1, p, dist[0], d );
00769 VJOIN1_2D( hit2, a, dist[1], c );
00770 VSUB2_2D( diff, hit1, hit2 );
00771 dist_sq = MAGSQ_2D( diff );
00772 if( dist_sq >= tol->dist_sq ) {
00773 if( bu_debug & BU_DEBUG_MATH || dist_sq < 100*tol->dist_sq ) {
00774 bu_log("bn_isect_line2_line2(): dist=%g >%g, inconsistent solution, hit1=(%g,%g), hit2=(%g,%g)\n",
00775 sqrt(dist_sq), tol->dist,
00776 hit1[X], hit1[Y], hit2[X], hit2[Y]);
00777 }
00778 return -2;
00779 }
00780 }
00781 #endif
00782
00783 return 1;
00784 }
00785
00786
00787
00788
00789
00790
00791
00792
00793
00794
00795
00796
00797
00798
00799
00800
00801
00802
00803
00804
00805
00806
00807
00808
00809
00810
00811
00812
00813
00814
00815
00816
00817
00818
00819
00820
00821
00822
00823
00824 int
00825 bn_isect_line2_lseg2(fastf_t *dist,
00826 const fastf_t *p,
00827 const fastf_t *d,
00828 const fastf_t *a,
00829 const fastf_t *c,
00830 const struct bn_tol *tol)
00831 {
00832 register fastf_t f;
00833 fastf_t ctol;
00834 int ret;
00835 point_t b;
00836
00837 BN_CK_TOL(tol);
00838 if( bu_debug & BU_DEBUG_MATH ) {
00839 bu_log("bn_isect_line2_lseg2() p=(%g,%g), pdir=(%g,%g)\n\t\t\ta=(%g,%g), adir=(%g,%g)\n",
00840 V2ARGS(p), V2ARGS(d), V2ARGS(a), V2ARGS(c) );
00841 }
00842
00843
00844
00845
00846
00847
00848
00849 if( (ctol = MAGSQ_2D(c)) <= tol->dist_sq ) {
00850 ret = -4;
00851 goto out;
00852 }
00853
00854
00855
00856
00857
00858
00859
00860 VADD2_2D( b, a, c );
00861 if( bn_distsq_line2_point2( p, d, a ) <= tol->dist_sq &&
00862 (ctol=bn_distsq_line2_point2( p, d, b )) <= tol->dist_sq ) {
00863 if( bu_debug & BU_DEBUG_MATH ) {
00864 bu_log("b=(%g, %g), b_dist_sq=%g\n", V2ARGS(b), ctol);
00865 bu_log("bn_isect_line2_lseg2() pts A and B within tol of line\n");
00866 }
00867
00868 dist[0] = bn_dist_pt2_along_line2( p, d, a );
00869 dist[1] = bn_dist_pt2_along_line2( p, d, b );
00870 ret = 0;
00871 goto out;
00872 }
00873
00874 if( (ret = bn_isect_line2_line2( dist, p, d, a, c, tol )) < 0 ) {
00875
00876 ret = -3;
00877 goto out;
00878 }
00879 if( ret == 0 ) {
00880 fastf_t dtol;
00881
00882
00883 dtol = tol->dist / sqrt(MAGSQ_2D(d));
00884 if( bu_debug & BU_DEBUG_MATH ) {
00885 bu_log("bn_isect_line2_lseg2() dtol=%g, dist[0]=%g, dist[1]=%g\n",
00886 dtol, dist[0], dist[1]);
00887 }
00888 if( dist[0] > -dtol && dist[0] < dtol ) dist[0] = 0;
00889 else if( dist[0] > 1-dtol && dist[0] < 1+dtol ) dist[0] = 1;
00890
00891 if( dist[1] > -dtol && dist[1] < dtol ) dist[1] = 0;
00892 else if( dist[1] > 1-dtol && dist[1] < 1+dtol ) dist[1] = 1;
00893 ret = 0;
00894 goto out;
00895 }
00896
00897
00898
00899
00900
00901
00902
00903
00904
00905 {
00906 fastf_t ab_dist = 0;
00907 point_t hit_pt;
00908 point_t hit2;
00909
00910 VJOIN1_2D( hit_pt, p, dist[0], d );
00911 VJOIN1_2D( hit2, a, dist[1], c );
00912
00913 if( bn_pt2_pt2_equal( a, hit_pt, tol ) ||
00914 bn_pt2_pt2_equal( a, hit2, tol ) ) {
00915 dist[1] = 0;
00916 ret = 1;
00917 }
00918 if( bn_pt2_pt2_equal( b, hit_pt, tol ) ||
00919 bn_pt2_pt2_equal( b, hit_pt, tol ) ) {
00920 dist[1] = 1;
00921 ret = 2;
00922 }
00923
00924 ret = bn_isect_pt2_lseg2( &ab_dist, a, b, hit_pt, tol );
00925 if( bu_debug & BU_DEBUG_MATH ) {
00926
00927 V2PRINT("a", a);
00928 V2PRINT("hit", hit_pt);
00929 V2PRINT("b", b);
00930 bu_log("bn_isect_pt2_lseg2() hit2d=(%g,%g) ab_dist=%g, ret=%d\n", hit_pt[X], hit_pt[Y], ab_dist, ret);
00931 bu_log("\tother hit2d=(%g,%g)\n", hit2[X], hit2[Y] );
00932 }
00933 if( ret <= 0 ) {
00934 if( ab_dist < 0 ) {
00935 ret = -2;
00936 } else {
00937 ret = -1;
00938 }
00939 goto out;
00940 }
00941 if( ret == 1 ) {
00942 dist[1] = 0;
00943 ret = 1;
00944 goto out;
00945 }
00946 if( ret == 2 ) {
00947 dist[1] = 1;
00948 ret = 2;
00949 goto out;
00950 }
00951
00952
00953 if( !bn_between( a[X], hit_pt[X], b[X], tol ) ||
00954 !bn_between( a[Y], hit_pt[Y], b[Y], tol ) ) {
00955 bu_bomb("bn_isect_line2_lseg2() hit_pt not between A and B!\n");
00956 }
00957 }
00958
00959
00960
00961
00962
00963
00964
00965
00966
00967 ctol = tol->dist / sqrt(ctol);
00968 if( bu_debug & BU_DEBUG_MATH ) {
00969 bu_log("bn_isect_line2_lseg2() ctol=%g, dist[1]=%g\n", ctol, dist[1]);
00970 }
00971 if( dist[1] < -ctol ) {
00972 ret = -2;
00973 goto out;
00974 }
00975 if( (f=(dist[1]-1)) > ctol ) {
00976 ret = -1;
00977 goto out;
00978 }
00979
00980
00981 if( dist[1] < ctol ) {
00982 dist[1] = 0;
00983 ret = 1;
00984 goto out;
00985 }
00986 if( f >= -ctol ) {
00987 dist[1] = 1;
00988 ret = 2;
00989 goto out;
00990 }
00991 ret = 3;
00992 out:
00993 if( bu_debug & BU_DEBUG_MATH ) {
00994 bu_log("bn_isect_line2_lseg2() dist[0]=%g, dist[1]=%g, ret=%d\n",
00995 dist[0], dist[1], ret);
00996 }
00997 return ret;
00998 }
00999
01000
01001
01002
01003
01004
01005
01006
01007
01008
01009
01010
01011
01012
01013
01014
01015
01016
01017
01018
01019
01020
01021
01022
01023
01024
01025
01026
01027
01028
01029
01030
01031
01032
01033
01034
01035 int
01036 bn_isect_lseg2_lseg2(fastf_t *dist,
01037 const fastf_t *p,
01038 const fastf_t *pdir,
01039 const fastf_t *q,
01040 const fastf_t *qdir,
01041 const struct bn_tol *tol)
01042 {
01043 fastf_t ptol, qtol;
01044 int status;
01045
01046 BN_CK_TOL(tol);
01047 if( bu_debug & BU_DEBUG_MATH ) {
01048 bu_log("bn_isect_lseg2_lseg2() p=(%g,%g), pdir=(%g,%g)\n\t\tq=(%g,%g), qdir=(%g,%g)\n",
01049 V2ARGS(p), V2ARGS(pdir), V2ARGS(q), V2ARGS(qdir) );
01050 }
01051
01052 status = bn_isect_line2_line2( dist, p, pdir, q, qdir, tol );
01053 if( status < 0 ) {
01054
01055 return -1;
01056 }
01057 if( status == 0 ) {
01058 int nogood = 0;
01059
01060
01061 ptol = tol->dist / sqrt( MAGSQ_2D(pdir) );
01062 if( bu_debug & BU_DEBUG_MATH ) {
01063 bu_log("ptol=%g\n", ptol);
01064 }
01065 if( dist[0] > -ptol && dist[0] < ptol ) dist[0] = 0;
01066 else if( dist[0] > 1-ptol && dist[0] < 1+ptol ) dist[0] = 1;
01067
01068 if( dist[1] > -ptol && dist[1] < ptol ) dist[1] = 0;
01069 else if( dist[1] > 1-ptol && dist[1] < 1+ptol ) dist[1] = 1;
01070
01071 if( dist[1] < 0 || dist[1] > 1 ) nogood = 1;
01072 if( dist[0] < 0 || dist[0] > 1 ) nogood++;
01073 if( nogood >= 2 )
01074 return -1;
01075 if( bu_debug & BU_DEBUG_MATH ) {
01076 bu_log(" HIT colinear!\n");
01077 }
01078 return 0;
01079 }
01080
01081
01082 ptol = tol->dist / sqrt( MAGSQ_2D(pdir) );
01083 if( dist[0] > -ptol && dist[0] < ptol ) dist[0] = 0;
01084 else if( dist[0] > 1-ptol && dist[0] < 1+ptol ) dist[0] = 1;
01085
01086 qtol = tol->dist / sqrt( MAGSQ_2D(qdir) );
01087 if( dist[1] > -qtol && dist[1] < qtol ) dist[1] = 0;
01088 else if( dist[1] > 1-qtol && dist[1] < 1+qtol ) dist[1] = 1;
01089
01090 if( bu_debug & BU_DEBUG_MATH ) {
01091 bu_log("ptol=%g, qtol=%g\n", ptol, qtol);
01092 }
01093 if( dist[0] < 0 || dist[0] > 1 || dist[1] < 0 || dist[1] > 1 ) {
01094 if( bu_debug & BU_DEBUG_MATH ) {
01095 bu_log(" MISS\n");
01096 }
01097 return -1;
01098 }
01099 if( bu_debug & BU_DEBUG_MATH ) {
01100 bu_log(" HIT!\n");
01101 }
01102 return 1;
01103 }
01104
01105
01106
01107
01108
01109
01110
01111
01112
01113
01114
01115
01116
01117
01118
01119
01120
01121
01122
01123
01124
01125
01126
01127
01128
01129
01130
01131
01132
01133
01134
01135
01136
01137 int
01138 bn_isect_lseg3_lseg3(fastf_t *dist,
01139 const fastf_t *p,
01140 const fastf_t *pdir,
01141 const fastf_t *q,
01142 const fastf_t *qdir,
01143 const struct bn_tol *tol)
01144 {
01145 fastf_t ptol, qtol;
01146 fastf_t pmag, qmag;
01147 int status;
01148
01149 BN_CK_TOL(tol);
01150 if( bu_debug & BU_DEBUG_MATH ) {
01151 bu_log("bn_isect_lseg3_lseg3() p=(%g,%g), pdir=(%g,%g)\n\t\tq=(%g,%g), qdir=(%g,%g)\n",
01152 V2ARGS(p), V2ARGS(pdir), V2ARGS(q), V2ARGS(qdir) );
01153 }
01154
01155 status = bn_isect_line3_line3( &dist[0], &dist[1], p, pdir, q, qdir, tol );
01156 if( status < 0 ) {
01157
01158 return -1;
01159 }
01160 pmag = MAGNITUDE(pdir);
01161 if( pmag < SMALL_FASTF )
01162 bu_bomb("bn_isect_lseg3_lseg3: |p|=0\n");
01163 if( status == 0 ) {
01164 int nogood = 0;
01165
01166
01167 ptol = tol->dist / pmag;
01168 if( bu_debug & BU_DEBUG_MATH ) {
01169 bu_log("ptol=%g\n", ptol);
01170 }
01171 if( dist[0] > -ptol && dist[0] < ptol ) dist[0] = 0;
01172 else if( dist[0] > 1-ptol && dist[0] < 1+ptol ) dist[0] = 1;
01173
01174 if( dist[1] > -ptol && dist[1] < ptol ) dist[1] = 0;
01175 else if( dist[1] > 1-ptol && dist[1] < 1+ptol ) dist[1] = 1;
01176
01177 if( dist[1] < 0 || dist[1] > 1 ) nogood = 1;
01178 if( dist[0] < 0 || dist[0] > 1 ) nogood++;
01179 if( nogood >= 2 )
01180 return -1;
01181 if( bu_debug & BU_DEBUG_MATH ) {
01182 bu_log(" HIT colinear!\n");
01183 }
01184 return 0;
01185 }
01186
01187
01188 ptol = tol->dist / pmag;
01189 if( dist[0] > -ptol && dist[0] < ptol ) dist[0] = 0;
01190 else if( dist[0] > 1-ptol && dist[0] < 1+ptol ) dist[0] = 1;
01191
01192 qmag = MAGNITUDE(qdir);
01193 if( qmag < SMALL_FASTF )
01194 bu_bomb("bn_isect_lseg3_lseg3: |q|=0\n");
01195 qtol = tol->dist / qmag;
01196 if( dist[1] > -qtol && dist[1] < qtol ) dist[1] = 0;
01197 else if( dist[1] > 1-qtol && dist[1] < 1+qtol ) dist[1] = 1;
01198
01199 if( bu_debug & BU_DEBUG_MATH ) {
01200 bu_log("ptol=%g, qtol=%g\n", ptol, qtol);
01201 }
01202 if( dist[0] < 0 || dist[0] > 1 || dist[1] < 0 || dist[1] > 1 ) {
01203 if( bu_debug & BU_DEBUG_MATH ) {
01204 bu_log(" MISS\n");
01205 }
01206 return -1;
01207 }
01208 if( bu_debug & BU_DEBUG_MATH ) {
01209 bu_log(" HIT!\n");
01210 }
01211 return 1;
01212 }
01213
01214
01215
01216
01217
01218
01219
01220
01221
01222
01223
01224
01225
01226
01227
01228
01229
01230
01231
01232
01233
01234
01235
01236
01237
01238
01239
01240
01241
01242
01243
01244
01245
01246
01247
01248
01249
01250
01251
01252
01253
01254
01255
01256 int
01257 bn_isect_line3_line3(fastf_t *t,
01258 fastf_t *u,
01259 const fastf_t *p,
01260 const fastf_t *d,
01261 const fastf_t *a,
01262 const fastf_t *c,
01263 const struct bn_tol *tol)
01264 {
01265 LOCAL vect_t n;
01266 LOCAL vect_t abs_n;
01267 LOCAL vect_t h;
01268 register fastf_t det;
01269 register fastf_t det1;
01270 register short int q,r,s;
01271
01272 BN_CK_TOL(tol);
01273
01274
01275
01276
01277
01278
01279
01280
01281
01282
01283
01284
01285
01286 VCROSS( n, d, c );
01287 det = VDOT( n, p ) - VDOT( n, a );
01288 if( !NEAR_ZERO( det, tol->dist ) ) {
01289 return(-1);
01290 }
01291
01292 if( NEAR_ZERO( MAGSQ( n ) , SMALL_FASTF ) )
01293 {
01294 vect_t a_to_p;
01295
01296
01297 VSUB2( a_to_p , p , a );
01298 VCROSS( n , a_to_p , d );
01299
01300 if( NEAR_ZERO( MAGSQ( n ) , SMALL_FASTF ) )
01301 bn_vec_ortho( n, d );
01302 }
01303
01304
01305
01306
01307
01308
01309
01310
01311
01312
01313
01314
01315
01316
01317
01318
01319
01320
01321
01322
01323
01324
01325 abs_n[X] = (n[X] >= 0) ? n[X] : (-n[X]);
01326 abs_n[Y] = (n[Y] >= 0) ? n[Y] : (-n[Y]);
01327 abs_n[Z] = (n[Z] >= 0) ? n[Z] : (-n[Z]);
01328 if( abs_n[X] >= abs_n[Y] ) {
01329 if( abs_n[X] >= abs_n[Z] ) {
01330
01331 q = Y;
01332 r = Z;
01333 s = X;
01334 } else {
01335
01336 q = X;
01337 r = Y;
01338 s = Z;
01339 }
01340 } else {
01341 if( abs_n[Y] >= abs_n[Z] ) {
01342
01343 q = X;
01344 r = Z;
01345 s = Y;
01346 } else {
01347
01348 q = X;
01349 r = Y;
01350 s = Z;
01351 }
01352 }
01353
01354 #if 0
01355
01356
01357 bn_isect_line2_line2( &dist, p, d, a, c, tol );
01358 #endif
01359
01360
01361
01362
01363
01364
01365
01366
01367
01368
01369
01370
01371
01372
01373
01374
01375
01376
01377
01378
01379
01380
01381
01382
01383
01384
01385
01386
01387
01388
01389
01390
01391 VSUB2( h, a, p );
01392 det = c[q] * d[r] - d[q] * c[r];
01393 det1 = (c[q] * h[r] - h[q] * c[r]);
01394
01395 if( NEAR_ZERO( det, DETERMINANT_TOL ) ) {
01396
01397 if( !NEAR_ZERO( det1, DETERMINANT_TOL ) ) {
01398
01399 return -2;
01400 }
01401
01402
01403
01404 *u = 0;
01405
01406 if( fabs(d[q]) >= fabs(d[r]) ) {
01407 *t = h[q]/d[q];
01408 } else {
01409 *t = h[r]/d[r];
01410 }
01411 return(0);
01412 }
01413
01414
01415
01416
01417
01418
01419
01420
01421
01422
01423
01424
01425
01426
01427
01428
01429
01430
01431
01432
01433
01434
01435
01436
01437 det = 1/det;
01438 *t = det * det1;
01439 *u = det * (d[q] * h[r] - h[q] * d[r]);
01440
01441
01442
01443
01444
01445
01446 det = *t * d[s] - *u * c[s] - h[s];
01447 if( !NEAR_ZERO( det, tol->dist ) ) {
01448
01449
01450
01451
01452 return(-1);
01453 }
01454
01455
01456
01457
01458 {
01459 point_t hit1, hit2;
01460
01461 VJOIN1( hit1, p, *t, d );
01462 VJOIN1( hit2, a, *u, c );
01463 if( !bn_pt3_pt3_equal( hit1, hit2, tol ) ) {
01464
01465
01466 return -1;
01467 }
01468 }
01469
01470 return(1);
01471 }
01472
01473
01474
01475
01476
01477
01478
01479
01480
01481
01482
01483
01484
01485
01486
01487
01488
01489
01490
01491
01492
01493
01494
01495
01496
01497
01498
01499
01500
01501
01502
01503
01504
01505
01506 int
01507 bn_isect_line_lseg(fastf_t *t, const fastf_t *p, const fastf_t *d, const fastf_t *a, const fastf_t *b, const struct bn_tol *tol)
01508 {
01509 LOCAL vect_t c;
01510 auto fastf_t u;
01511 register fastf_t f;
01512 register int ret;
01513 fastf_t fuzz;
01514
01515 BN_CK_TOL(tol);
01516
01517 VSUB2( c, b, a );
01518
01519
01520
01521
01522
01523
01524 if( (fuzz = MAGSQ(c)) < tol->dist_sq ) {
01525 return(-4);
01526 }
01527
01528
01529
01530
01531
01532
01533
01534 if( bn_distsq_line3_pt3( p, d, a ) <= tol->dist_sq &&
01535 bn_distsq_line3_pt3( p, d, b ) <= tol->dist_sq ) {
01536 if( bu_debug & BU_DEBUG_MATH ) {
01537 bu_log("bn_isect_line3_lseg3() pts A and B within tol of line\n");
01538 }
01539
01540 *t = bn_dist_pt3_along_line3( p, d, a );
01541
01542 return 0;
01543 }
01544
01545 if( (ret = bn_isect_line3_line3( t, &u, p, d, a, c, tol )) < 0 ) {
01546
01547 return( -1 );
01548 }
01549 if( ret == 0 ) {
01550
01551 return( 0 );
01552 }
01553
01554
01555
01556
01557
01558
01559
01560
01561
01562
01563 fuzz = tol->dist / sqrt(fuzz);
01564 if( u < -fuzz )
01565 return(-3);
01566 if( (f=(u-1)) > fuzz )
01567 return(-2);
01568
01569
01570 if( u < fuzz )
01571 return( 1 );
01572 if( f >= -fuzz )
01573 return( 2 );
01574
01575 return(3);
01576 }
01577
01578
01579
01580
01581
01582
01583
01584
01585
01586
01587
01588
01589
01590
01591
01592
01593
01594 double
01595 bn_dist_line3_pt3(const fastf_t *pt, const fastf_t *dir, const fastf_t *a)
01596 {
01597 LOCAL vect_t f;
01598 register fastf_t FdotD;
01599
01600 if( (FdotD = MAGNITUDE(dir)) <= SMALL_FASTF ) {
01601 FdotD = 0.0;
01602 goto out;
01603 }
01604 VSUB2( f, a, pt );
01605 FdotD = VDOT( f, dir ) / FdotD;
01606 FdotD = MAGSQ( f ) - FdotD * FdotD;
01607 if( FdotD <= SMALL_FASTF ) {
01608 FdotD = 0.0;
01609 goto out;
01610 }
01611 FdotD = sqrt(FdotD);
01612 out:
01613 if( bu_debug & BU_DEBUG_MATH ) {
01614 bu_log("bn_dist_line3_pt3() ret=%g\n", FdotD);
01615 }
01616 return FdotD;
01617 }
01618
01619
01620
01621
01622
01623
01624
01625
01626
01627
01628
01629
01630 double
01631 bn_distsq_line3_pt3(const fastf_t *pt, const fastf_t *dir, const fastf_t *a)
01632 {
01633 LOCAL vect_t f;
01634 register fastf_t FdotD;
01635
01636 VSUB2( f, pt, a );
01637 if( (FdotD = MAGNITUDE(dir)) <= SMALL_FASTF ) {
01638 FdotD = 0.0;
01639 goto out;
01640 }
01641 FdotD = VDOT( f, dir ) / FdotD;
01642 if( (FdotD = VDOT( f, f ) - FdotD * FdotD ) <= SMALL_FASTF ) {
01643 FdotD = 0.0;
01644 }
01645 out:
01646 if( bu_debug & BU_DEBUG_MATH ) {
01647 bu_log("bn_distsq_line3_pt3() ret=%g\n", FdotD);
01648 }
01649 return FdotD;
01650 }
01651
01652
01653
01654
01655
01656
01657
01658
01659
01660
01661
01662 double
01663 bn_dist_line_origin(const fastf_t *pt, const fastf_t *dir)
01664 {
01665 register fastf_t PTdotD;
01666
01667 if( (PTdotD = MAGNITUDE(dir)) <= SMALL_FASTF )
01668 return 0.0;
01669 PTdotD = VDOT( pt, dir ) / PTdotD;
01670 if( (PTdotD = VDOT( pt, pt ) - PTdotD * PTdotD ) <= SMALL_FASTF )
01671 return(0.0);
01672 return( sqrt(PTdotD) );
01673 }
01674
01675
01676
01677
01678
01679
01680
01681
01682
01683
01684 double
01685 bn_dist_line2_point2(const fastf_t *pt, const fastf_t *dir, const fastf_t *a)
01686 {
01687 LOCAL vect_t f;
01688 register fastf_t FdotD;
01689
01690 VSUB2_2D( f, pt, a );
01691 if( (FdotD = sqrt(MAGSQ_2D(dir))) <= SMALL_FASTF )
01692 return 0.0;
01693 FdotD = VDOT_2D( f, dir ) / FdotD;
01694 if( (FdotD = VDOT_2D( f, f ) - FdotD * FdotD ) <= SMALL_FASTF )
01695 return(0.0);
01696 return( sqrt(FdotD) );
01697 }
01698
01699
01700
01701
01702
01703
01704
01705
01706
01707
01708
01709
01710 double
01711 bn_distsq_line2_point2(const fastf_t *pt, const fastf_t *dir, const fastf_t *a)
01712 {
01713 LOCAL vect_t f;
01714 register fastf_t FdotD;
01715
01716 VSUB2_2D( f, pt, a );
01717 if( (FdotD = sqrt(MAGSQ_2D(dir))) <= SMALL_FASTF )
01718 return 0.0;
01719 FdotD = VDOT_2D( f, dir ) / FdotD;
01720 if( (FdotD = VDOT_2D( f, f ) - FdotD * FdotD ) <= SMALL_FASTF )
01721 return(0.0);
01722 return( FdotD );
01723 }
01724
01725
01726
01727
01728
01729
01730
01731 double
01732 bn_area_of_triangle(register const fastf_t *a, register const fastf_t *b, register const fastf_t *c)
01733 {
01734 register double t;
01735 register double area;
01736
01737 t = a[Y] * (b[Z] - c[Z]) -
01738 b[Y] * (a[Z] - c[Z]) +
01739 c[Y] * (a[Z] - b[Z]);
01740 area = t*t;
01741 t = a[Z] * (b[X] - c[X]) -
01742 b[Z] * (a[X] - c[X]) +
01743 c[Z] * (a[X] - b[X]);
01744 area += t*t;
01745 t = a[X] * (b[Y] - c[Y]) -
01746 b[X] * (a[Y] - c[Y]) +
01747 c[X] * (a[Y] - b[Y]);
01748 area += t*t;
01749
01750 return( 0.5 * sqrt(area) );
01751 }
01752
01753
01754
01755
01756
01757
01758
01759
01760
01761
01762
01763
01764
01765
01766
01767
01768
01769
01770
01771
01772
01773
01774
01775
01776
01777
01778
01779
01780
01781
01782
01783
01784
01785
01786
01787
01788 int bn_isect_pt_lseg(fastf_t *dist,
01789 const fastf_t *a,
01790 const fastf_t *b,
01791 const fastf_t *p,
01792 const struct bn_tol *tol)
01793
01794
01795
01796 {
01797 vect_t AtoP,
01798 BtoP,
01799 AtoB,
01800 ABunit;
01801 fastf_t APprABunit;
01802 fastf_t distsq;
01803
01804 BN_CK_TOL(tol);
01805
01806 VSUB2(AtoP, p, a);
01807 if (MAGSQ(AtoP) < tol->dist_sq)
01808 return(1);
01809
01810 VSUB2(BtoP, p, b);
01811 if (MAGSQ(BtoP) < tol->dist_sq)
01812 return(2);
01813
01814 VSUB2(AtoB, b, a);
01815 VMOVE(ABunit, AtoB);
01816 distsq = MAGSQ(ABunit);
01817 if( distsq < tol->dist_sq )
01818 return -1;
01819 distsq = 1/sqrt(distsq);
01820 VSCALE( ABunit, ABunit, distsq );
01821
01822
01823
01824
01825
01826
01827
01828
01829 APprABunit = VDOT(AtoP, ABunit);
01830
01831
01832 distsq = MAGSQ(AtoP) - APprABunit * APprABunit;
01833 if (distsq > tol->dist_sq)
01834 return(-1);
01835
01836
01837 *dist = VDOT(AtoP, AtoB) / MAGSQ(AtoB);
01838
01839 if (*dist > 1.0 || *dist < 0.0)
01840 return(-2);
01841
01842 return(3);
01843 }
01844
01845
01846
01847
01848
01849
01850
01851
01852
01853
01854
01855
01856
01857
01858
01859
01860
01861
01862
01863
01864
01865
01866
01867
01868
01869
01870
01871
01872
01873 int
01874 bn_isect_pt2_lseg2(fastf_t *dist, const fastf_t *a, const fastf_t *b, const fastf_t *p, const struct bn_tol *tol)
01875
01876
01877
01878 {
01879 vect_t AtoP,
01880 BtoP,
01881 AtoB,
01882 ABunit;
01883 fastf_t APprABunit;
01884 fastf_t distsq;
01885
01886 BN_CK_TOL(tol);
01887
01888 VSUB2_2D(AtoP, p, a);
01889 if (MAGSQ_2D(AtoP) < tol->dist_sq)
01890 return(1);
01891
01892 VSUB2_2D(BtoP, p, b);
01893 if (MAGSQ_2D(BtoP) < tol->dist_sq)
01894 return(2);
01895
01896 VSUB2_2D(AtoB, b, a);
01897 VMOVE_2D(ABunit, AtoB);
01898 distsq = MAGSQ_2D(ABunit);
01899 if( distsq < tol->dist_sq ) {
01900 if( bu_debug & BU_DEBUG_MATH ) {
01901 bu_log("distsq A=%g\n", distsq);
01902 }
01903 return -1;
01904 }
01905 distsq = 1/sqrt(distsq);
01906 VSCALE_2D( ABunit, ABunit, distsq );
01907
01908
01909
01910
01911
01912
01913
01914
01915 APprABunit = VDOT_2D(AtoP, ABunit);
01916
01917
01918 distsq = MAGSQ_2D(AtoP) - APprABunit * APprABunit;
01919 if (distsq > tol->dist_sq) {
01920 if( bu_debug & BU_DEBUG_MATH ) {
01921 V2PRINT("ABunit", ABunit);
01922 bu_log("distsq B=%g\n", distsq);
01923 }
01924 return(-1);
01925 }
01926
01927
01928 *dist = VDOT_2D(AtoP, AtoB) / MAGSQ_2D(AtoB);
01929
01930 if (*dist > 1.0 || *dist < 0.0)
01931 return(-2);
01932
01933 return(3);
01934 }
01935
01936
01937
01938
01939
01940
01941
01942
01943
01944
01945
01946
01947
01948
01949
01950
01951
01952
01953
01954
01955
01956
01957
01958
01959
01960
01961
01962
01963
01964
01965
01966
01967
01968 int
01969 bn_dist_pt3_lseg3(fastf_t *dist,
01970 fastf_t *pca,
01971 const fastf_t *a,
01972 const fastf_t *b,
01973 const fastf_t *p,
01974 const struct bn_tol *tol)
01975 {
01976 vect_t PtoA;
01977 vect_t PtoB;
01978 vect_t AtoB;
01979 fastf_t P_A_sq;
01980 fastf_t P_B_sq;
01981 fastf_t B_A;
01982 fastf_t t;
01983
01984 BN_CK_TOL(tol);
01985
01986 if( bu_debug & BU_DEBUG_MATH ) {
01987 bu_log("bn_dist_pt3_lseg3() a=(%g,%g,%g) b=(%g,%g,%g)\n\tp=(%g,%g,%g), tol->dist=%g sq=%g\n",
01988 V3ARGS(a),
01989 V3ARGS(b),
01990 V3ARGS(p),
01991 tol->dist, tol->dist_sq );
01992 }
01993
01994
01995 VSUB2(PtoA, p, a);
01996 if( (P_A_sq = MAGSQ(PtoA)) < tol->dist_sq ) {
01997
01998 VMOVE( pca, a );
01999 if( bu_debug & BU_DEBUG_MATH ) bu_log(" at A\n");
02000 *dist = 0.0;
02001 return 1;
02002 }
02003
02004
02005 VSUB2(PtoB, p, b);
02006 if( (P_B_sq = MAGSQ(PtoB)) < tol->dist_sq ) {
02007
02008 VMOVE( pca, b );
02009 if( bu_debug & BU_DEBUG_MATH ) bu_log(" at B\n");
02010 *dist = 0.0;
02011 return 2;
02012 }
02013
02014 VSUB2(AtoB, b, a);
02015 B_A = sqrt( MAGSQ(AtoB) );
02016
02017
02018
02019
02020 t = VDOT(PtoA, AtoB) / B_A;
02021 if( bu_debug & BU_DEBUG_MATH ) {
02022 bu_log("bn_dist_pt3_lseg3() B_A=%g, t=%g\n",
02023 B_A, t );
02024 }
02025
02026 if( t <= 0 ) {
02027
02028 if( bu_debug & BU_DEBUG_MATH ) bu_log(" left of A\n");
02029 VMOVE( pca, a );
02030 *dist = sqrt(P_A_sq);
02031 return 3;
02032 }
02033 if( t < B_A ) {
02034
02035 register fastf_t dsq;
02036 fastf_t param_dist;
02037
02038
02039 param_dist = t / B_A;
02040 VJOIN1(pca, a, param_dist, AtoB);
02041
02042
02043 if( (dsq = P_A_sq - t * t ) <= tol->dist_sq ) {
02044 if( bu_debug & BU_DEBUG_MATH ) bu_log(" ON lseg\n");
02045
02046 *dist = param_dist;
02047 return 0;
02048 }
02049 if( bu_debug & BU_DEBUG_MATH ) bu_log(" closest to lseg\n");
02050 *dist = sqrt(dsq);
02051 return 5;
02052 }
02053
02054 if( bu_debug & BU_DEBUG_MATH ) bu_log(" right of B\n");
02055 VMOVE(pca, b);
02056 *dist = sqrt(P_B_sq);
02057 return 4;
02058 }
02059
02060
02061
02062
02063
02064
02065
02066
02067
02068
02069
02070
02071
02072
02073
02074
02075
02076
02077
02078
02079
02080
02081
02082
02083
02084
02085
02086
02087
02088
02089 int
02090 bn_dist_pt2_lseg2(fastf_t *dist_sq, fastf_t *pca, const fastf_t *a, const fastf_t *b, const fastf_t *p, const struct bn_tol *tol)
02091 {
02092 vect_t PtoA;
02093 vect_t PtoB;
02094 vect_t AtoB;
02095 fastf_t P_A_sq;
02096 fastf_t P_B_sq;
02097 fastf_t B_A;
02098 fastf_t t;
02099
02100 BN_CK_TOL(tol);
02101
02102 if( bu_debug & BU_DEBUG_MATH ) {
02103 bu_log("bn_dist_pt3_lseg3() a=(%g,%g,%g) b=(%g,%g,%g)\n\tp=(%g,%g,%g), tol->dist=%g sq=%g\n",
02104 V3ARGS(a),
02105 V3ARGS(b),
02106 V3ARGS(p),
02107 tol->dist, tol->dist_sq );
02108 }
02109
02110
02111
02112 VSUB2_2D(PtoA, p, a);
02113 if( (P_A_sq = MAGSQ_2D(PtoA)) < tol->dist_sq ) {
02114
02115 V2MOVE( pca, a );
02116 if( bu_debug & BU_DEBUG_MATH ) bu_log(" at A\n");
02117 *dist_sq = 0.0;
02118 return 1;
02119 }
02120
02121
02122 VSUB2_2D(PtoB, p, b);
02123 if( (P_B_sq = MAGSQ_2D(PtoB)) < tol->dist_sq ) {
02124
02125 V2MOVE( pca, b );
02126 if( bu_debug & BU_DEBUG_MATH ) bu_log(" at B\n");
02127 *dist_sq = 0.0;
02128 return 2;
02129 }
02130
02131 VSUB2_2D(AtoB, b, a);
02132 B_A = sqrt( MAGSQ_2D(AtoB) );
02133
02134
02135
02136
02137 t = VDOT_2D(PtoA, AtoB) / B_A;
02138 if( bu_debug & BU_DEBUG_MATH ) {
02139 bu_log("bn_dist_pt3_lseg3() B_A=%g, t=%g\n",
02140 B_A, t );
02141 }
02142
02143 if( t <= 0 ) {
02144
02145 if( bu_debug & BU_DEBUG_MATH ) bu_log(" left of A\n");
02146 V2MOVE( pca, a );
02147 *dist_sq = P_A_sq;
02148 return 3;
02149 }
02150 if( t < B_A ) {
02151
02152 register fastf_t dsq;
02153 fastf_t param_dist;
02154
02155
02156 param_dist = t / B_A;
02157 V2JOIN1(pca, a, param_dist, AtoB);
02158
02159
02160 if( (dsq = P_A_sq - t * t ) <= tol->dist_sq ) {
02161 if( bu_debug & BU_DEBUG_MATH ) bu_log(" ON lseg\n");
02162
02163 *dist_sq = param_dist;
02164 return 0;
02165 }
02166 if( bu_debug & BU_DEBUG_MATH ) bu_log(" closest to lseg\n");
02167 *dist_sq = dsq;
02168 return 5;
02169 }
02170
02171 if( bu_debug & BU_DEBUG_MATH ) bu_log(" right of B\n");
02172 V2MOVE(pca, b);
02173 *dist_sq = P_B_sq;
02174 return 4;
02175 }
02176
02177
02178
02179
02180
02181
02182
02183
02184
02185
02186 void
02187 bn_rotate_bbox(fastf_t *omin, fastf_t *omax, const fastf_t *mat, const fastf_t *imin, const fastf_t *imax)
02188 {
02189 point_t local;
02190 point_t model;
02191
02192 #define ROT_VERT( a, b, c ) \
02193 VSET( local, a[X], b[Y], c[Z] ); \
02194 MAT4X3PNT( model, mat, local ); \
02195 VMINMAX( omin, omax, model ) \
02196
02197 ROT_VERT( imin, imin, imin );
02198 ROT_VERT( imin, imin, imax );
02199 ROT_VERT( imin, imax, imin );
02200 ROT_VERT( imin, imax, imax );
02201 ROT_VERT( imax, imin, imin );
02202 ROT_VERT( imax, imin, imax );
02203 ROT_VERT( imax, imax, imin );
02204 ROT_VERT( imax, imax, imax );
02205 #undef ROT_VERT
02206 }
02207
02208
02209
02210
02211
02212
02213 void
02214 bn_rotate_plane(fastf_t *oplane, const fastf_t *mat, const fastf_t *iplane)
02215 {
02216 point_t orig_pt;
02217 point_t new_pt;
02218
02219
02220 VSCALE( orig_pt, iplane, iplane[3] );
02221
02222
02223 MAT4X3VEC( oplane, mat, iplane );
02224
02225
02226 MAT4X3PNT( new_pt, mat, orig_pt );
02227
02228
02229
02230
02231
02232 oplane[3] = VDOT( new_pt, oplane );
02233 }
02234
02235
02236
02237
02238
02239
02240
02241
02242
02243
02244
02245
02246
02247 int
02248 bn_coplanar(const fastf_t *a, const fastf_t *b, const struct bn_tol *tol)
02249 {
02250 register fastf_t f;
02251 register fastf_t dot;
02252
02253 BN_CK_TOL(tol);
02254
02255
02256 dot = VDOT( a, b );
02257 if( dot >= 0 ) {
02258
02259 if( dot < tol->para )
02260 return(0);
02261
02262
02263 f = a[3] - b[3];
02264 if( NEAR_ZERO( f, tol->dist ) ) {
02265 return(1);
02266 }
02267 return(-1);
02268 }
02269
02270 if( -dot < tol->para )
02271 return(0);
02272
02273
02274 f = a[3] + b[3];
02275 if( NEAR_ZERO( f, tol->dist ) ) {
02276 return(2);
02277 }
02278 return(-1);
02279 }
02280
02281
02282
02283
02284
02285
02286
02287
02288
02289
02290
02291
02292
02293
02294
02295
02296
02297
02298
02299
02300
02301
02302
02303
02304
02305
02306
02307
02308
02309
02310
02311
02312 double
02313 bn_angle_measure(fastf_t *vec, const fastf_t *x_dir, const fastf_t *y_dir)
02314 {
02315 fastf_t xproj, yproj;
02316 fastf_t gamma;
02317 fastf_t ang;
02318
02319 xproj = -VDOT( vec, x_dir );
02320 yproj = -VDOT( vec, y_dir );
02321 gamma = atan2( yproj, xproj );
02322 ang = bn_pi + gamma;
02323 if( ang < 0 ) {
02324 do {
02325 ang += bn_twopi;
02326 } while( ang < 0 );
02327 } else if( ang > bn_twopi ) {
02328 do {
02329 ang -= bn_twopi;
02330 } while( ang > bn_twopi );
02331 }
02332 if( ang < 0 || ang > bn_twopi ) bu_bomb("bn_angle_measure() angle out of range\n");
02333 return ang;
02334 }
02335
02336
02337
02338
02339
02340
02341
02342
02343
02344 double
02345 bn_dist_pt3_along_line3(const fastf_t *p, const fastf_t *d, const fastf_t *x)
02346 {
02347 vect_t x_p;
02348
02349 VSUB2( x_p, x, p );
02350 return VDOT( x_p, d );
02351 }
02352
02353
02354
02355
02356
02357
02358
02359
02360
02361
02362 double
02363 bn_dist_pt2_along_line2(const fastf_t *p, const fastf_t *d, const fastf_t *x)
02364 {
02365 vect_t x_p;
02366 double ret;
02367
02368 VSUB2_2D( x_p, x, p );
02369 ret = VDOT_2D( x_p, d );
02370 if( bu_debug & BU_DEBUG_MATH ) {
02371 bu_log("bn_dist_pt2_along_line2() p=(%g, %g), d=(%g, %g), x=(%g, %g) ret=%g\n",
02372 V2ARGS(p),
02373 V2ARGS(d),
02374 V2ARGS(x),
02375 ret );
02376 }
02377 return ret;
02378 }
02379
02380
02381
02382
02383
02384
02385 int
02386 bn_between(double left, double mid, double right, const struct bn_tol *tol)
02387 {
02388 BN_CK_TOL(tol);
02389
02390 if( left < right ) {
02391 if( NEAR_ZERO(left-right, tol->dist*0.1) ) {
02392 left -= tol->dist*0.1;
02393 right += tol->dist*0.1;
02394 }
02395 if( mid < left || mid > right ) goto fail;
02396 return 1;
02397 }
02398
02399 if( NEAR_ZERO(left-right, tol->dist*0.1) ) {
02400 right -= tol->dist*0.1;
02401 left += tol->dist*0.1;
02402 }
02403 if( mid < right || mid > left ) goto fail;
02404 return 1;
02405 fail:
02406 if( bu_debug & BU_DEBUG_MATH ) {
02407 bu_log("bn_between( %.17e, %.17e, %.17e ) ret=0 FAIL\n",
02408 left, mid, right);
02409 }
02410 return 0;
02411 }
02412
02413
02414
02415
02416
02417
02418
02419
02420 int
02421 bn_does_ray_isect_tri(
02422 const point_t pt,
02423 const vect_t dir,
02424 const point_t V,
02425 const point_t A,
02426 const point_t B,
02427 point_t inter)
02428 {
02429 vect_t VP, VA, VB, AB, AP, N;
02430 fastf_t NdotDir;
02431 plane_t pl;
02432 fastf_t dist;
02433
02434
02435
02436 VSUB2( VA, A, V );
02437 VSUB2( VB, B, V );
02438 VCROSS( pl, VA, VB );
02439 VUNITIZE( pl );
02440
02441 NdotDir = VDOT( pl, dir );
02442 if( NEAR_ZERO( NdotDir, SMALL_FASTF ) )
02443 return( 0 );
02444
02445 pl[3] = VDOT( pl, V );
02446
02447 dist = (pl[3] - VDOT( pl, pt ))/NdotDir;
02448 VJOIN1( inter, pt, dist, dir );
02449
02450
02451 VSUB2( VP, inter, V );
02452 VCROSS( N, VA, VP );
02453 if( VDOT( N, pl ) < 0.0 )
02454 return( 0 );
02455
02456 VCROSS( N, VP, VB );
02457 if( VDOT( N, pl ) < 0.0 )
02458 return( 0 );
02459
02460 VSUB2( AB, B, A );
02461 VSUB2( AP, inter, A );
02462 VCROSS( N, AB, AP );
02463 if( VDOT( N, pl ) < 0.0 )
02464 return( 0 );
02465
02466 return( 1 );
02467 }
02468
02469 #if 0
02470
02471
02472
02473
02474
02475
02476
02477
02478
02479
02480
02481
02482
02483
02484
02485
02486
02487
02488
02489
02490
02491
02492
02493
02494
02495
02496
02497
02498
02499
02500
02501
02502
02503
02504
02505
02506
02507
02508
02509
02510
02511 int
02512 bn_isect_ray_tri(dist_p, N_p, Alpha_p, Beta_p, pt, dir, V, A, B)
02513 fastf_t *dist_p;
02514 fastf_t *N_p;
02515 fastf_t *Alpha_p;
02516 fastf_t *Beta_p;
02517 const point_t pt;
02518 const vect_t dir;
02519 const point_t V;
02520 const point_t A;
02521 const point_t B;
02522 {
02523 vect_t VA;
02524 vect_t VB;
02525 vect_t pt_V;
02526 vect_t N;
02527 vect_t VPP;
02528 fastf_t alpha;
02529 fastf_t beta;
02530 fastf_t NdotDir;
02531 fastf_t entleave;
02532 fastf_t k;
02533
02534
02535 VSUB2(VB, B, V);
02536 VSUB2(VA, A, V);
02537
02538
02539 VCROSS( N, VA, VB );
02540
02541 NdotDir = VDOT( N, dir );
02542 if (fabs(NdotDir) < SQRT_SMALL_FASTF)
02543 return 0;
02544
02545 if (NdotDir >= 0.0) entleave = -1;
02546 else entleave = 1;
02547
02548 VSUB2( pt_V, V, pt );
02549 VCROSS( VPP, pt_V, dir );
02550
02551
02552
02553
02554
02555 alpha = VDOT( VA, VPP ) * entleave;
02556 if (alpha < 0.0 || alpha > fabs(NdotDir) ) return 0;
02557
02558
02559
02560 beta = VDOT(VB, VPP ) * (-1 * entleave);
02561 if (beta < 0.0 || beta > fabs(NdotDir)) return 0;
02562
02563 k = VDOT(VPP, N) / NdotDir;
02564
02565 if (dist_p) *dist_p = k;
02566 if (N_p) {
02567 VUNITIZE(N);
02568 VMOVE(N_p, N);
02569 }
02570 if (Alpha_p) *Alpha_p = alpha;
02571 if (Beta_p) *Beta_p = beta;
02572
02573 return entleave;
02574 }
02575 #endif
02576
02577
02578
02579
02580
02581
02582
02583
02584
02585
02586
02587
02588 int
02589 bn_hlf_class(const fastf_t *half_eqn, const fastf_t *min, const fastf_t *max, const struct bn_tol *tol)
02590 {
02591 int class;
02592 fastf_t d;
02593
02594 #define CHECK_PT( x, y, z ) \
02595 d = (x)*half_eqn[0] + (y)*half_eqn[1] + (z)*half_eqn[2] - half_eqn[3];\
02596 if( d < -tol->dist ) { \
02597 if( class == BN_CLASSIFY_OUTSIDE ) \
02598 return BN_CLASSIFY_OVERLAPPING; \
02599 else class = BN_CLASSIFY_INSIDE; \
02600 } else if( d > tol->dist ) { \
02601 if( class == BN_CLASSIFY_INSIDE ) \
02602 return BN_CLASSIFY_OVERLAPPING; \
02603 else class = BN_CLASSIFY_OUTSIDE; \
02604 } else return BN_CLASSIFY_OVERLAPPING
02605
02606 class = BN_CLASSIFY_UNIMPLEMENTED;
02607 CHECK_PT( min[X], min[Y], min[Z] );
02608 CHECK_PT( min[X], min[Y], max[Z] );
02609 CHECK_PT( min[X], max[Y], min[Z] );
02610 CHECK_PT( min[X], max[Y], max[Z] );
02611 CHECK_PT( max[X], min[Y], min[Z] );
02612 CHECK_PT( max[X], min[Y], max[Z] );
02613 CHECK_PT( max[X], max[Y], min[Z] );
02614 CHECK_PT( max[X], max[Y], max[Z] );
02615 if( class == BN_CLASSIFY_UNIMPLEMENTED )
02616 bu_log( "bn_hlf_class: error in implementation\
02617 min = (%g, %g, %g), max = (%g, %g, %g), half_eqn = (%d, %d, %d, %d)\n",
02618 V3ARGS(min), V3ARGS(max), V3ARGS(half_eqn),
02619 half_eqn[3]);
02620 return class;
02621 }
02622
02623
02624
02625
02626
02627
02628
02629
02630
02631
02632
02633
02634
02635
02636
02637
02638
02639
02640
02641
02642
02643
02644
02645
02646 int
02647 bn_distsq_line3_line3(fastf_t *dist, fastf_t *P, fastf_t *d_in, fastf_t *Q, fastf_t *e_in, fastf_t *pt1, fastf_t *pt2)
02648 {
02649 fastf_t de, denom;
02650 vect_t diff, PmQ, tmp;
02651 vect_t d, e;
02652 fastf_t len_e, inv_len_e, len_d, inv_len_d;
02653 int ret=0;
02654
02655 len_e = MAGNITUDE( e_in );
02656 if( NEAR_ZERO( len_e, SMALL_FASTF ) )
02657 bu_bomb( "bn_distsq_line3_line3() called with zero length vector!!!\n");
02658 inv_len_e = 1.0 / len_e;
02659
02660 len_d = MAGNITUDE( d_in );
02661 if( NEAR_ZERO( len_d, SMALL_FASTF ) )
02662 bu_bomb( "bn_distsq_line3_line3() called with zero length vector!!!\n");
02663 inv_len_d = 1.0 / len_d;
02664
02665 VSCALE( e, e_in, inv_len_e );
02666 VSCALE( d, d_in, inv_len_d );
02667 de = VDOT( d, e );
02668
02669 if( NEAR_ZERO( de, SMALL_FASTF ) )
02670 {
02671
02672 dist[0] = VDOT( Q, d ) - VDOT( P, d );
02673 dist[1] = VDOT( P, e ) - VDOT( Q, e );
02674 }
02675 else
02676 {
02677 VSUB2( PmQ, P, Q );
02678 denom = 1.0 - de*de;
02679 if( NEAR_ZERO( denom, SMALL_FASTF ) )
02680 {
02681
02682 dist[0] = 0.0;
02683 dist[1] = VDOT( PmQ, d );
02684 ret = 1;
02685 }
02686 else
02687 {
02688 VBLEND2( tmp, 1.0, e, -de, d );
02689 dist[1] = VDOT( PmQ, tmp )/denom;
02690 dist[0] = dist[1] * de - VDOT( PmQ, d );
02691 }
02692 }
02693 VJOIN1( pt1, P, dist[0], d );
02694 VJOIN1( pt2, Q, dist[1], e );
02695 VSUB2( diff, pt1, pt2 );
02696 dist[0] *= inv_len_d;
02697 dist[1] *= inv_len_e;
02698 dist[2] = MAGSQ( diff );
02699 return( ret );
02700 }
02701
02702
02703
02704
02705
02706
02707
02708
02709
02710
02711
02712
02713
02714
02715
02716
02717
02718
02719
02720
02721
02722
02723
02724
02725
02726
02727 int
02728 bn_isect_planes(fastf_t *pt, const fastf_t (*planes)[4], const int pl_count)
02729 {
02730 mat_t matrix;
02731 mat_t inverse;
02732 vect_t hpq;
02733 fastf_t det;
02734 int i;
02735
02736 if( bu_debug & BU_DEBUG_MATH ) {
02737 bu_log( "bn_isect_planes:\n" );
02738 for( i=0 ; i<pl_count ; i++ )
02739 {
02740 bu_log( "Plane #%d (%f %f %f %f)\n" , i , V4ARGS( planes[i] ) );
02741 }
02742 }
02743
02744 MAT_ZERO( matrix );
02745 VSET( hpq , 0.0 , 0.0 , 0.0 );
02746
02747 for( i=0 ; i<pl_count ; i++ )
02748 {
02749 matrix[0] += planes[i][X] * planes[i][X];
02750 matrix[5] += planes[i][Y] * planes[i][Y];
02751 matrix[10] += planes[i][Z] * planes[i][Z];
02752 matrix[1] += planes[i][X] * planes[i][Y];
02753 matrix[2] += planes[i][X] * planes[i][Z];
02754 matrix[6] += planes[i][Y] * planes[i][Z];
02755 hpq[X] += planes[i][X] * planes[i][H];
02756 hpq[Y] += planes[i][Y] * planes[i][H];
02757 hpq[Z] += planes[i][Z] * planes[i][H];
02758 }
02759
02760 matrix[4] = matrix[1];
02761 matrix[8] = matrix[2];
02762 matrix[9] = matrix[6];
02763 matrix[15] = 1.0;
02764
02765
02766 det = bn_mat_determinant( matrix );
02767 if( NEAR_ZERO( det , SMALL_FASTF ) )
02768 return( 1 );
02769
02770 bn_mat_inv( inverse , matrix );
02771
02772 MAT4X3PNT( pt , inverse , hpq );
02773
02774 return( 0 );
02775
02776 }
02777
02778
02779
02780
02781
02782
02783
02784
02785
02786
02787
02788
02789
02790
02791
02792
02793
02794
02795
02796
02797
02798 int
02799 bn_isect_lseg_rpp(fastf_t *a,
02800 fastf_t *b,
02801 register fastf_t *min,
02802 register fastf_t *max)
02803 {
02804 auto vect_t diff;
02805 register fastf_t *pt = &a[0];
02806 register fastf_t *dir = &diff[0];
02807 register int i;
02808 register double sv;
02809 register double st;
02810 register double mindist, maxdist;
02811
02812 mindist = -MAX_FASTF;
02813 maxdist = MAX_FASTF;
02814 VSUB2( diff, b, a );
02815
02816 for( i=0; i < 3; i++, pt++, dir++, max++, min++ ) {
02817 if( *dir < -SQRT_SMALL_FASTF ) {
02818 if( (sv = (*min - *pt) / *dir) < 0.0 )
02819 return(0);
02820 if(maxdist > sv)
02821 maxdist = sv;
02822 if( mindist < (st = (*max - *pt) / *dir) )
02823 mindist = st;
02824 } else if( *dir > SQRT_SMALL_FASTF ) {
02825 if( (st = (*max - *pt) / *dir) < 0.0 )
02826 return(0);
02827 if(maxdist > st)
02828 maxdist = st;
02829 if( mindist < ((sv = (*min - *pt) / *dir)) )
02830 mindist = sv;
02831 } else {
02832
02833
02834
02835
02836
02837 if( (*min > *pt) || (*max < *pt) )
02838 return(0); ;
02839 }
02840 }
02841 if( mindist >= maxdist )
02842 return(0);
02843
02844 if( mindist > 1 || maxdist < 0 )
02845 return(0);
02846
02847 if( mindist >= 0 && maxdist <= 1 )
02848 return(1);
02849
02850
02851 if( mindist < 0 )
02852 mindist = 0;
02853 if( maxdist > 1 )
02854 maxdist = 1;
02855
02856
02857 VJOIN1( b, a, maxdist, diff );
02858 VJOIN1( a, a, mindist, diff );
02859 return(1);
02860 }
02861
02862
02863
02864
02865
02866
02867
02868
02869
02870
02871