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
00039
00040
00041
00042
00043
00044
00045
00046
00047
00048
00049
00050
00051
00052
00053
00054
00055
00056
00057
00058
00059
00060
00061
00062
00063
00064
00065
00066
00067
00068
00069
00070
00071
00072 #ifndef lint
00073 static const char bn_RCSmat[] = "@(#)$Header: /cvsroot/brlcad/brlcad/src/libbn/mat.c,v 14.13 2006/09/02 14:02:15 lbutler Exp $ (ARL)";
00074 #endif
00075
00076 #include "common.h"
00077
00078
00079
00080 #include <stdio.h>
00081 #include <math.h>
00082
00083 #ifdef HAVE_STRING_H
00084 #include <string.h>
00085 #else
00086 #include <strings.h>
00087 #endif
00088
00089 #include "machine.h"
00090 #include "bu.h"
00091 #include "vmath.h"
00092 #include "bn.h"
00093
00094 const mat_t bn_mat_identity = {
00095 1.0, 0.0, 0.0, 0.0,
00096 0.0, 1.0, 0.0, 0.0,
00097 0.0, 0.0, 1.0, 0.0,
00098 0.0, 0.0, 0.0, 1.0
00099 };
00100
00101
00102
00103
00104 void
00105 bn_mat_print_guts(const char *title,
00106 const mat_t m,
00107 char *obuf)
00108 {
00109 register int i;
00110 register char *cp;
00111
00112 sprintf(obuf, "MATRIX %s:\n ", title);
00113 cp = obuf+strlen(obuf);
00114 if (!m) {
00115 strcat(obuf, "(Identity)");
00116 } else {
00117 for (i=0; i<16; i++) {
00118 sprintf(cp, " %8.3f", m[i]);
00119 cp += strlen(cp);
00120 if (i == 15) {
00121 break;
00122 } else if((i&3) == 3) {
00123 *cp++ = '\n';
00124 *cp++ = ' ';
00125 *cp++ = ' ';
00126 }
00127 }
00128 *cp++ = '\0';
00129 }
00130 }
00131
00132
00133
00134
00135 void
00136 bn_mat_print(const char *title,
00137 const mat_t m)
00138 {
00139 char obuf[1024];
00140
00141 bn_mat_print_guts(title, m, obuf);
00142 bu_log("%s\n", obuf);
00143 }
00144
00145
00146
00147
00148
00149
00150
00151 double
00152 bn_atan2(double y, double x)
00153 {
00154 if( x > -1.0e-20 && x < 1.0e-20 ) {
00155
00156 if( y < -1.0e-20 ) return( -3.14159265358979323/2 );
00157 if( y > 1.0e-20 ) return( 3.14159265358979323/2 );
00158 return(0.0);
00159 }
00160 return( atan2( y, x ) );
00161 }
00162
00163 #if 0
00164
00165
00166
00167
00168
00169
00170 void
00171 bn_mat_zero( m )
00172 mat_t m;
00173 {
00174 register int i = 0;
00175 register matp_t mp = m;
00176
00177 bu_log("libbn/mat.c: bn_mat_zero() is deprecated, use MAT_ZERO()\n");
00178
00179 for(; i<16; i++)
00180 *mp++ = 0.0;
00181 }
00182
00183
00184
00185
00186
00187
00188
00189
00190 void
00191 bn_mat_idn( m )
00192 register mat_t m;
00193 {
00194 bu_log("libbn/mat.c: bn_mat_idn() is deprecated, use MAT_IDN()\n");
00195 memcpy(m, bn_mat_identity, sizeof(m));
00196 }
00197
00198
00199
00200
00201
00202 void
00203 bn_mat_copy( dest, src )
00204 register mat_t dest;
00205 register const mat_t src;
00206 {
00207 register int i;
00208
00209
00210 # include "noalias.h"
00211 bu_log("libbn/mat.c: bn_mat_copy() is deprecated, use MAT_COPY()\n");
00212 for( i=15; i>=0; i--)
00213 dest[i] = src[i];
00214 }
00215
00216 #endif
00217
00218
00219
00220
00221
00222
00223
00224
00225
00226 void
00227 bn_mat_mul(register mat_t o, register const mat_t a, register const mat_t b)
00228 {
00229 o[ 0] = a[ 0]*b[ 0] + a[ 1]*b[ 4] + a[ 2]*b[ 8] + a[ 3]*b[12];
00230 o[ 1] = a[ 0]*b[ 1] + a[ 1]*b[ 5] + a[ 2]*b[ 9] + a[ 3]*b[13];
00231 o[ 2] = a[ 0]*b[ 2] + a[ 1]*b[ 6] + a[ 2]*b[10] + a[ 3]*b[14];
00232 o[ 3] = a[ 0]*b[ 3] + a[ 1]*b[ 7] + a[ 2]*b[11] + a[ 3]*b[15];
00233
00234 o[ 4] = a[ 4]*b[ 0] + a[ 5]*b[ 4] + a[ 6]*b[ 8] + a[ 7]*b[12];
00235 o[ 5] = a[ 4]*b[ 1] + a[ 5]*b[ 5] + a[ 6]*b[ 9] + a[ 7]*b[13];
00236 o[ 6] = a[ 4]*b[ 2] + a[ 5]*b[ 6] + a[ 6]*b[10] + a[ 7]*b[14];
00237 o[ 7] = a[ 4]*b[ 3] + a[ 5]*b[ 7] + a[ 6]*b[11] + a[ 7]*b[15];
00238
00239 o[ 8] = a[ 8]*b[ 0] + a[ 9]*b[ 4] + a[10]*b[ 8] + a[11]*b[12];
00240 o[ 9] = a[ 8]*b[ 1] + a[ 9]*b[ 5] + a[10]*b[ 9] + a[11]*b[13];
00241 o[10] = a[ 8]*b[ 2] + a[ 9]*b[ 6] + a[10]*b[10] + a[11]*b[14];
00242 o[11] = a[ 8]*b[ 3] + a[ 9]*b[ 7] + a[10]*b[11] + a[11]*b[15];
00243
00244 o[12] = a[12]*b[ 0] + a[13]*b[ 4] + a[14]*b[ 8] + a[15]*b[12];
00245 o[13] = a[12]*b[ 1] + a[13]*b[ 5] + a[14]*b[ 9] + a[15]*b[13];
00246 o[14] = a[12]*b[ 2] + a[13]*b[ 6] + a[14]*b[10] + a[15]*b[14];
00247 o[15] = a[12]*b[ 3] + a[13]*b[ 7] + a[14]*b[11] + a[15]*b[15];
00248 }
00249
00250
00251
00252
00253
00254
00255
00256
00257
00258
00259 void
00260 bn_mat_mul2(register const mat_t i, register mat_t o)
00261 {
00262 mat_t temp;
00263
00264 bn_mat_mul( temp, i, o );
00265 MAT_COPY( o, temp );
00266 }
00267
00268
00269
00270
00271
00272
00273
00274
00275 void
00276 bn_mat_mul3(mat_t o, const mat_t a, const mat_t b, const mat_t c)
00277 {
00278 mat_t t;
00279
00280 bn_mat_mul( t, b, c );
00281 bn_mat_mul( o, a, t );
00282 }
00283
00284
00285
00286
00287
00288
00289
00290
00291 void
00292 bn_mat_mul4(mat_t ao, const mat_t a, const mat_t b, const mat_t c, const mat_t d)
00293 {
00294 mat_t t, u;
00295
00296 bn_mat_mul( u, c, d );
00297 bn_mat_mul( t, a, b );
00298 bn_mat_mul( ao, t, u );
00299 }
00300
00301
00302
00303
00304
00305
00306
00307
00308 void
00309 bn_matXvec(register vect_t ov, register const mat_t im, register const vect_t iv)
00310 {
00311 register int eo = 0;
00312 register int em = 0;
00313 register int ei;
00314
00315
00316 for(; eo<4; eo++) {
00317
00318 ov[eo] = 0;
00319
00320 for(ei=0; ei<4; ei++)
00321 ov[eo] += im[em++] * iv[ei];
00322 }
00323 }
00324
00325
00326
00327
00328
00329
00330
00331
00332
00333
00334 void
00335 bn_mat_inv(register mat_t output, const mat_t input)
00336 {
00337 if(bn_mat_inverse(output, input) == 0) {
00338 bu_log("bn_mat_inv: error!");
00339 bn_mat_print("singular matrix", input);
00340 bu_bomb("bn_mat_inv: singular matrix\n");
00341
00342 }
00343 }
00344
00345
00346
00347
00348
00349
00350
00351
00352
00353
00354
00355
00356
00357
00358
00359
00360 int
00361 bn_mat_inverse(register mat_t output, const mat_t input)
00362 {
00363 register int i, j;
00364 LOCAL int k;
00365 LOCAL int z[4];
00366 LOCAL fastf_t b[4];
00367 LOCAL fastf_t c[4];
00368
00369 MAT_COPY( output, input );
00370
00371
00372 for( j = 0; j < 4; j++ )
00373 z[j] = j;
00374
00375
00376 for( i = 0; i < 4; i++ ) {
00377 FAST fastf_t y;
00378
00379 k = i;
00380 y = output[i*4+i];
00381 for( j = i+1; j < 4; j++ ) {
00382 FAST fastf_t w;
00383
00384 w = output[i*4+j];
00385 if( fabs(w) > fabs(y) ) {
00386 k = j;
00387 y = w;
00388 }
00389 }
00390
00391 if( fabs(y) < SQRT_SMALL_FASTF ) {
00392 return 0;
00393
00394 }
00395 y = 1.0 / y;
00396
00397 for( j = 0; j < 4; j++ ) {
00398 FAST fastf_t temp;
00399
00400 c[j] = output[j*4+k];
00401 output[j*4+k] = output[j*4+i];
00402 output[j*4+i] = - c[j] * y;
00403 temp = output[i*4+j] * y;
00404 b[j] = temp;
00405 output[i*4+j] = temp;
00406 }
00407
00408 output[i*4+i] = y;
00409 j = z[i];
00410 z[i] = z[k];
00411 z[k] = j;
00412 for( k = 0; k < 4; k++ ) {
00413 if( k == i ) continue;
00414 for( j = 0; j < 4; j++ ) {
00415 if( j == i ) continue;
00416 output[k*4+j] = output[k*4+j] - b[j] * c[k];
00417 }
00418 }
00419 }
00420
00421
00422 for( i = 0; i < 4; i++ ) {
00423 while( (k = z[i]) != i ) {
00424 LOCAL int p;
00425
00426 for( j = 0; j < 4; j++ ) {
00427 FAST fastf_t w;
00428
00429 w = output[i*4+j];
00430 output[i*4+j] = output[k*4+j];
00431 output[k*4+j] = w;
00432 }
00433 p = z[i];
00434 z[i] = z[k];
00435 z[k] = p;
00436 }
00437 }
00438
00439 return 1;
00440 }
00441
00442
00443
00444
00445
00446
00447
00448
00449
00450
00451
00452
00453
00454
00455
00456
00457
00458
00459
00460
00461
00462
00463
00464
00465 void
00466 bn_htov_move(register vect_t v, register const vect_t h)
00467 {
00468 register fastf_t inv;
00469
00470 if( h[3] == 1.0 ) {
00471 v[X] = h[X];
00472 v[Y] = h[Y];
00473 v[Z] = h[Z];
00474 } else {
00475 if( h[W] == SMALL_FASTF ) {
00476 bu_log("bn_htov_move: divide by %f!\n", h[W]);
00477 return;
00478 }
00479 inv = 1.0 / h[W];
00480 v[X] = h[X] * inv;
00481 v[Y] = h[Y] * inv;
00482 v[Z] = h[Z] * inv;
00483 }
00484 }
00485
00486
00487
00488
00489
00490 void
00491 bn_mat_trn(mat_t om, register const mat_t im)
00492 {
00493 register matp_t op = om;
00494
00495 *op++ = im[0];
00496 *op++ = im[4];
00497 *op++ = im[8];
00498 *op++ = im[12];
00499
00500 *op++ = im[1];
00501 *op++ = im[5];
00502 *op++ = im[9];
00503 *op++ = im[13];
00504
00505 *op++ = im[2];
00506 *op++ = im[6];
00507 *op++ = im[10];
00508 *op++ = im[14];
00509
00510 *op++ = im[3];
00511 *op++ = im[7];
00512 *op++ = im[11];
00513 *op++ = im[15];
00514 }
00515
00516
00517
00518
00519
00520
00521
00522
00523
00524
00525 void
00526 bn_mat_ae(register fastf_t *m, double azimuth, double elev)
00527 {
00528 LOCAL double sin_az, sin_el;
00529 LOCAL double cos_az, cos_el;
00530
00531 azimuth *= bn_degtorad;
00532 elev *= bn_degtorad;
00533
00534 sin_az = sin(azimuth);
00535 cos_az = cos(azimuth);
00536 sin_el = sin(elev);
00537 cos_el = cos(elev);
00538
00539 m[0] = cos_el * cos_az;
00540 m[1] = -sin_az;
00541 m[2] = -sin_el * cos_az;
00542 m[3] = 0;
00543
00544 m[4] = cos_el * sin_az;
00545 m[5] = cos_az;
00546 m[6] = -sin_el * sin_az;
00547 m[7] = 0;
00548
00549 m[8] = sin_el;
00550 m[9] = 0;
00551 m[10] = cos_el;
00552 m[11] = 0;
00553
00554 m[12] = m[13] = m[14] = 0;
00555 m[15] = 1.0;
00556 }
00557
00558
00559
00560
00561
00562
00563
00564 void
00565 bn_ae_vec(fastf_t *azp, fastf_t *elp, const vect_t v)
00566 {
00567 register fastf_t az;
00568
00569 if( (az = bn_atan2( v[Y], v[X] ) * bn_radtodeg) < 0 ) {
00570 *azp = 360 + az;
00571 } else if( az >= 360 ) {
00572 *azp = az - 360;
00573 } else {
00574 *azp = az;
00575 }
00576 *elp = bn_atan2( v[Z], hypot( v[X], v[Y] ) ) * bn_radtodeg;
00577 }
00578
00579
00580
00581
00582
00583
00584
00585
00586
00587
00588 void
00589 bn_aet_vec(fastf_t *az, fastf_t *el, fastf_t *twist, fastf_t *vec_ae, fastf_t *vec_twist, fastf_t accuracy)
00590 {
00591 vect_t zero_twist,ninety_twist;
00592 vect_t z_dir;
00593
00594
00595 bn_ae_vec( az , el , vec_ae );
00596
00597
00598
00599 if( NEAR_ZERO( *az - 360.0 , accuracy ) )
00600 *az = 0.0;
00601
00602
00603 if( NEAR_ZERO( *el - 90.0 , accuracy ) || NEAR_ZERO( *el + 90.0 , accuracy ) )
00604 {
00605 *twist = 0.0;
00606 *az = bn_atan2( -vec_twist[X] , vec_twist[Y] ) * bn_radtodeg;
00607 }
00608 else
00609 {
00610
00611 VSET( z_dir , 0 , 0 , 1 );
00612 VCROSS( zero_twist , z_dir , vec_ae );
00613 VUNITIZE( zero_twist );
00614 VCROSS( ninety_twist , vec_ae , zero_twist );
00615 VUNITIZE( ninety_twist );
00616
00617 *twist = bn_atan2( VDOT( vec_twist , ninety_twist ) , VDOT( vec_twist , zero_twist ) ) * bn_radtodeg;
00618
00619
00620 if( NEAR_ZERO( *twist + 180.0 , accuracy ) )
00621 *twist = 180.0;
00622 }
00623 }
00624
00625
00626
00627
00628
00629
00630
00631
00632
00633
00634
00635
00636 void
00637 bn_mat_angles(register fastf_t *mat, double alpha_in, double beta_in, double ggamma_in)
00638 {
00639 LOCAL double alpha, beta, ggamma;
00640 LOCAL double calpha, cbeta, cgamma;
00641 LOCAL double salpha, sbeta, sgamma;
00642
00643 if( alpha_in == 0.0 && beta_in == 0.0 && ggamma_in == 0.0 ) {
00644 MAT_IDN( mat );
00645 return;
00646 }
00647
00648 alpha = alpha_in * bn_degtorad;
00649 beta = beta_in * bn_degtorad;
00650 ggamma = ggamma_in * bn_degtorad;
00651
00652 calpha = cos( alpha );
00653 cbeta = cos( beta );
00654 cgamma = cos( ggamma );
00655
00656
00657
00658
00659
00660
00661 if( alpha_in == 180.0 )
00662 salpha = 0.0;
00663 else
00664 salpha = sin( alpha );
00665
00666 if( beta_in == 180.0 )
00667 sbeta = 0.0;
00668 else
00669 sbeta = sin( beta );
00670
00671 if( ggamma_in == 180.0 )
00672 sgamma = 0.0;
00673 else
00674 sgamma = sin( ggamma );
00675
00676 mat[0] = cbeta * cgamma;
00677 mat[1] = -cbeta * sgamma;
00678 mat[2] = sbeta;
00679 mat[3] = 0.0;
00680
00681 mat[4] = salpha * sbeta * cgamma + calpha * sgamma;
00682 mat[5] = -salpha * sbeta * sgamma + calpha * cgamma;
00683 mat[6] = -salpha * cbeta;
00684 mat[7] = 0.0;
00685
00686 mat[8] = salpha * sgamma - calpha * sbeta * cgamma;
00687 mat[9] = salpha * cgamma + calpha * sbeta * sgamma;
00688 mat[10] = calpha * cbeta;
00689 mat[11] = 0.0;
00690 mat[12] = mat[13] = mat[14] = 0.0;
00691 mat[15] = 1.0;
00692 }
00693
00694
00695
00696
00697
00698
00699
00700
00701
00702
00703
00704 void
00705 bn_mat_angles_rad(register mat_t mat,
00706 double alpha,
00707 double beta,
00708 double ggamma)
00709 {
00710 LOCAL double calpha, cbeta, cgamma;
00711 LOCAL double salpha, sbeta, sgamma;
00712
00713 if (alpha == 0.0 && beta == 0.0 && ggamma == 0.0) {
00714 MAT_IDN( mat );
00715 return;
00716 }
00717
00718 calpha = cos( alpha );
00719 cbeta = cos( beta );
00720 cgamma = cos( ggamma );
00721
00722 salpha = sin( alpha );
00723 sbeta = sin( beta );
00724 sgamma = sin( ggamma );
00725
00726 mat[0] = cbeta * cgamma;
00727 mat[1] = -cbeta * sgamma;
00728 mat[2] = sbeta;
00729 mat[3] = 0.0;
00730
00731 mat[4] = salpha * sbeta * cgamma + calpha * sgamma;
00732 mat[5] = -salpha * sbeta * sgamma + calpha * cgamma;
00733 mat[6] = -salpha * cbeta;
00734 mat[7] = 0.0;
00735
00736 mat[8] = salpha * sgamma - calpha * sbeta * cgamma;
00737 mat[9] = salpha * cgamma + calpha * sbeta * sgamma;
00738 mat[10] = calpha * cbeta;
00739 mat[11] = 0.0;
00740 mat[12] = mat[13] = mat[14] = 0.0;
00741 mat[15] = 1.0;
00742 }
00743
00744
00745
00746
00747
00748
00749
00750
00751
00752
00753
00754
00755 void
00756 bn_eigen2x2(fastf_t *val1, fastf_t *val2, fastf_t *vec1, fastf_t *vec2, fastf_t a, fastf_t b, fastf_t c)
00757 {
00758 fastf_t d, root;
00759 fastf_t v1, v2;
00760
00761 d = 0.5 * (c - a);
00762
00763
00764 if( NEAR_ZERO(b, 1.0e-10) ) {
00765
00766 if( fabs(c) < fabs(a) ) {
00767 *val1 = c;
00768 VSET( vec1, 0.0, 1.0, 0.0 );
00769 *val2 = a;
00770 VSET( vec2, -1.0, 0.0, 0.0 );
00771 } else {
00772 *val1 = a;
00773 VSET( vec1, 1.0, 0.0, 0.0 );
00774 *val2 = c;
00775 VSET( vec2, 0.0, 1.0, 0.0 );
00776 }
00777 return;
00778 }
00779
00780 root = sqrt( d*d + b*b );
00781 v1 = 0.5 * (c + a) - root;
00782 v2 = 0.5 * (c + a) + root;
00783
00784
00785 if( fabs(v1) < fabs(v2) ) {
00786 *val1 = v1;
00787 *val2 = v2;
00788 VSET( vec1, b, d - root, 0.0 );
00789 } else {
00790 *val1 = v2;
00791 *val2 = v1;
00792 VSET( vec1, root - d, b, 0.0 );
00793 }
00794 VUNITIZE( vec1 );
00795 VSET( vec2, -vec1[Y], vec1[X], 0.0 );
00796 }
00797
00798
00799
00800
00801
00802
00803
00804 void
00805 bn_vec_perp(vect_t new, const vect_t old)
00806 {
00807 register int i;
00808 LOCAL vect_t another;
00809
00810 i = X;
00811 if( fabs(old[Y])<fabs(old[i]) ) i=Y;
00812 if( fabs(old[Z])<fabs(old[i]) ) i=Z;
00813 VSETALL( another, 0 );
00814 another[i] = 1.0;
00815 if( old[X] == 0 && old[Y] == 0 && old[Z] == 0 ) {
00816 VMOVE( new, another );
00817 } else {
00818 VCROSS( new, another, old );
00819 }
00820 }
00821
00822
00823
00824
00825
00826
00827
00828
00829
00830
00831
00832 void
00833 bn_mat_fromto(mat_t m, const vect_t from, const vect_t to)
00834 {
00835 vect_t test_to;
00836 vect_t unit_from, unit_to;
00837 fastf_t dot;
00838
00839
00840
00841
00842
00843
00844 mat_t Q, Qt;
00845 mat_t R;
00846 mat_t A;
00847 mat_t temp;
00848 vect_t N, M;
00849 vect_t w_prime;
00850
00851 VMOVE( unit_from, from );
00852 VUNITIZE( unit_from );
00853 VMOVE( unit_to, to );
00854 VUNITIZE( unit_to );
00855
00856
00857
00858
00859
00860 dot = VDOT(unit_from, unit_to);
00861 if( dot > 1.0-0.00001 ) {
00862
00863 MAT_IDN(m);
00864 return;
00865 }
00866 if( dot < -1.0+0.00001 ) {
00867
00868 bn_vec_perp( N, unit_from );
00869 } else {
00870 VCROSS( N, unit_from, unit_to );
00871 VUNITIZE( N );
00872 }
00873 VCROSS( M, N, unit_from );
00874 VUNITIZE( M );
00875
00876
00877 MAT_IDN( Q );
00878 VMOVE( &Q[0], unit_from );
00879 VMOVE( &Q[4], M );
00880 VMOVE( &Q[8], N );
00881 bn_mat_trn( Qt, Q );
00882
00883
00884 MAT4X3VEC( w_prime, Q, unit_to );
00885
00886 MAT_IDN( R );
00887 VMOVE( &R[0], w_prime );
00888 VSET( &R[4], -w_prime[Y], w_prime[X], w_prime[Z] );
00889 VSET( &R[8], 0, 0, 1 );
00890
00891 bn_mat_mul( temp, R, Q );
00892 bn_mat_mul( A, Qt, temp );
00893 bn_mat_trn( m, A );
00894
00895
00896 MAT4X3VEC( test_to, m, unit_from );
00897 dot = VDOT( unit_to, test_to );
00898 if( dot < 0.98 || dot > 1.02 ) {
00899 bu_log("bn_mat_fromto() ERROR! from (%g,%g,%g) to (%g,%g,%g) went to (%g,%g,%g), dot=%g?\n",
00900 V3ARGS(from),
00901 V3ARGS(to),
00902 V3ARGS( test_to ), dot );
00903 }
00904 }
00905
00906
00907
00908
00909
00910
00911 void
00912 bn_mat_xrot(fastf_t *m, double sinx, double cosx)
00913 {
00914 m[0] = 1.0;
00915 m[1] = 0.0;
00916 m[2] = 0.0;
00917 m[3] = 0.0;
00918
00919 m[4] = 0.0;
00920 m[5] = cosx;
00921 m[6] = -sinx;
00922 m[7] = 0.0;
00923
00924 m[8] = 0.0;
00925 m[9] = sinx;
00926 m[10] = cosx;
00927 m[11] = 0.0;
00928
00929 m[12] = m[13] = m[14] = 0.0;
00930 m[15] = 1.0;
00931 }
00932
00933
00934
00935
00936
00937
00938 void
00939 bn_mat_yrot(fastf_t *m, double siny, double cosy)
00940 {
00941 m[0] = cosy;
00942 m[1] = 0.0;
00943 m[2] = -siny;
00944 m[3] = 0.0;
00945
00946 m[4] = 0.0;
00947 m[5] = 1.0;
00948 m[6] = 0.0;
00949 m[7] = 0.0;
00950
00951 m[8] = siny;
00952 m[9] = 0.0;
00953 m[10] = cosy;
00954
00955 m[11] = 0.0;
00956 m[12] = m[13] = m[14] = 0.0;
00957 m[15] = 1.0;
00958 }
00959
00960
00961
00962
00963
00964
00965 void
00966 bn_mat_zrot(fastf_t *m, double sinz, double cosz)
00967 {
00968 m[0] = cosz;
00969 m[1] = -sinz;
00970 m[2] = 0.0;
00971 m[3] = 0.0;
00972
00973 m[4] = sinz;
00974 m[5] = cosz;
00975 m[6] = 0.0;
00976 m[7] = 0.0;
00977
00978 m[8] = 0.0;
00979 m[9] = 0.0;
00980 m[10] = 1.0;
00981 m[11] = 0.0;
00982
00983 m[12] = m[13] = m[14] = 0.0;
00984 m[15] = 1.0;
00985 }
00986
00987
00988
00989
00990
00991
00992
00993
00994
00995
00996
00997
00998
00999
01000
01001
01002
01003
01004
01005
01006
01007
01008
01009 void
01010 bn_mat_lookat(mat_t rot, const vect_t dir, int yflip)
01011 {
01012 mat_t first;
01013 mat_t second;
01014 mat_t prod12;
01015 mat_t third;
01016 vect_t x;
01017 vect_t z;
01018 vect_t t1;
01019 fastf_t hypot_xy;
01020 vect_t xproj;
01021 vect_t zproj;
01022
01023
01024 hypot_xy = hypot( dir[X], dir[Y] );
01025 bn_mat_zrot( first, -dir[Y] / hypot_xy, dir[X] / hypot_xy );
01026
01027
01028 bn_mat_yrot( second, -hypot_xy, -dir[Z] );
01029 bn_mat_mul( prod12, second, first );
01030
01031
01032 VSET( x, 1, 0, 0 );
01033 MAT4X3VEC( xproj, prod12, x );
01034 hypot_xy = hypot( xproj[X], xproj[Y] );
01035 if( hypot_xy < 1.0e-10 ) {
01036 bu_log("Warning: bn_mat_lookat: unable to twist correct, hypot=%g\n", hypot_xy);
01037 VPRINT( "xproj", xproj );
01038 MAT_COPY( rot, prod12 );
01039 return;
01040 }
01041 bn_mat_zrot( third, -xproj[Y] / hypot_xy, xproj[X] / hypot_xy );
01042 bn_mat_mul( rot, third, prod12 );
01043
01044 if( yflip ) {
01045 VSET( z, 0, 0, 1 );
01046 MAT4X3VEC( zproj, rot, z );
01047
01048 if( zproj[Y] < 0.0 ) {
01049 MAT_COPY( prod12, rot );
01050 MAT_IDN( third );
01051 third[5] = -1;
01052 bn_mat_mul( rot, third, prod12 );
01053 }
01054 }
01055
01056
01057 MAT4X3VEC( t1, rot, dir );
01058 if( t1[Z] > -0.98 ) {
01059 bu_log("Error: bn_mat_lookat final= (%g, %g, %g)\n", t1[X], t1[Y], t1[Z] );
01060 }
01061 }
01062
01063
01064
01065
01066
01067
01068
01069
01070 void
01071 bn_vec_ortho(register vect_t out, register const vect_t in)
01072 {
01073 register int j, k;
01074 FAST fastf_t f;
01075 register int i;
01076
01077 if( NEAR_ZERO(in[X], 0.0001) && NEAR_ZERO(in[Y], 0.0001) &&
01078 NEAR_ZERO(in[Z], 0.0001) ) {
01079 VSETALL( out, 0 );
01080 VPRINT("bn_vec_ortho: zero-length input", in);
01081 return;
01082 }
01083
01084
01085 f = fabs(in[X]);
01086 i = X;
01087 j = Y;
01088 k = Z;
01089 if( fabs(in[Y]) < f ) {
01090 f = fabs(in[Y]);
01091 i = Y;
01092 j = Z;
01093 k = X;
01094 }
01095 if( fabs(in[Z]) < f ) {
01096 i = Z;
01097 j = X;
01098 k = Y;
01099 }
01100 f = hypot( in[j], in[k] );
01101 if( NEAR_ZERO( f, SMALL ) ) {
01102 VPRINT("bn_vec_ortho: zero hypot on", in);
01103 VSETALL( out, 0 );
01104 return;
01105 }
01106 f = 1.0/f;
01107 out[i] = 0.0;
01108 out[j] = -in[k]*f;
01109 out[k] = in[j]*f;
01110 }
01111
01112
01113
01114
01115
01116
01117
01118
01119
01120
01121
01122 int
01123 bn_mat_scale_about_pt(mat_t mat, const point_t pt, const double scale)
01124 {
01125 mat_t xlate;
01126 mat_t s;
01127 mat_t tmp;
01128
01129 MAT_IDN( xlate );
01130 MAT_DELTAS_VEC_NEG( xlate, pt );
01131
01132 MAT_IDN( s );
01133 if( NEAR_ZERO( scale, SMALL ) ) {
01134 MAT_ZERO( mat );
01135 return -1;
01136 }
01137 s[15] = 1/scale;
01138
01139 bn_mat_mul( tmp, s, xlate );
01140
01141 MAT_DELTAS_VEC( xlate, pt );
01142 bn_mat_mul( mat, xlate, tmp );
01143 return 0;
01144 }
01145
01146
01147
01148
01149
01150
01151 void
01152 bn_mat_xform_about_pt(mat_t mat, const mat_t xform, const point_t pt)
01153 {
01154 mat_t xlate;
01155 mat_t tmp;
01156
01157 MAT_IDN( xlate );
01158 MAT_DELTAS_VEC_NEG( xlate, pt );
01159
01160 bn_mat_mul( tmp, xform, xlate );
01161
01162 MAT_DELTAS_VEC( xlate, pt );
01163 bn_mat_mul( mat, xlate, tmp );
01164 }
01165
01166
01167
01168
01169
01170
01171
01172
01173 int
01174 bn_mat_is_equal(const mat_t a, const mat_t b, const struct bn_tol *tol)
01175 {
01176 register int i;
01177 register double f;
01178 register double tdist, tperp;
01179
01180 BN_CK_TOL(tol);
01181
01182 tdist = tol->dist;
01183 tperp = tol->perp;
01184
01185
01186
01187
01188
01189
01190
01191 for (i=3; i<12; i+=4) {
01192 f = a[i] - b[i];
01193 if ( !NEAR_ZERO(f, tdist)) return 0;
01194 }
01195
01196
01197
01198
01199
01200 for (i = 0; i < 16; i+=4) {
01201 f = a[i] - b[i];
01202 if ( !NEAR_ZERO(f, tperp)) return 0;
01203 f = a[i+1] - b[i+1];
01204 if ( !NEAR_ZERO(f, tperp)) return 0;
01205 f = a[i+2] - b[i+2];
01206 if ( !NEAR_ZERO(f, tperp)) return 0;
01207 }
01208
01209
01210
01211
01212
01213 f = a[15] - b[15];
01214 if ( !NEAR_ZERO(f, tperp)) return 0;
01215
01216 return 1;
01217 }
01218
01219
01220
01221
01222
01223
01224
01225
01226
01227
01228
01229
01230
01231
01232
01233 int
01234 bn_mat_is_identity(const mat_t m)
01235 {
01236 return (! memcmp(m, bn_mat_identity, sizeof(mat_t)));
01237 }
01238
01239
01240
01241
01242
01243
01244
01245
01246
01247 void
01248 bn_mat_arb_rot(mat_t m, const point_t pt, const vect_t dir, const fastf_t ang)
01249 {
01250 mat_t tran1,tran2,rot;
01251 double cos_ang, sin_ang, one_m_cosang;
01252 double n1_sq, n2_sq, n3_sq;
01253 double n1_n2, n1_n3, n2_n3;
01254
01255 if( ang == 0.0 )
01256 {
01257 MAT_IDN( m );
01258 return;
01259 }
01260
01261 MAT_IDN( tran1 );
01262 MAT_IDN( tran2 );
01263
01264
01265 tran1[MDX] = (-pt[X]);
01266 tran1[MDY] = (-pt[Y]);
01267 tran1[MDZ] = (-pt[Z]);
01268
01269
01270 tran2[MDX] = pt[X];
01271 tran2[MDY] = pt[Y];
01272 tran2[MDZ] = pt[Z];
01273
01274
01275 cos_ang = cos( ang );
01276 sin_ang = sin( ang );
01277 one_m_cosang = 1.0 - cos_ang;
01278 n1_sq = dir[X]*dir[X];
01279 n2_sq = dir[Y]*dir[Y];
01280 n3_sq = dir[Z]*dir[Z];
01281 n1_n2 = dir[X]*dir[Y];
01282 n1_n3 = dir[X]*dir[Z];
01283 n2_n3 = dir[Y]*dir[Z];
01284
01285 MAT_IDN( rot );
01286 rot[0] = n1_sq + (1.0 - n1_sq)*cos_ang;
01287 rot[1] = n1_n2 * one_m_cosang - dir[Z]*sin_ang;
01288 rot[2] = n1_n3 * one_m_cosang + dir[Y]*sin_ang;
01289
01290 rot[4] = n1_n2 * one_m_cosang + dir[Z]*sin_ang;
01291 rot[5] = n2_sq + (1.0 - n2_sq)*cos_ang;
01292 rot[6] = n2_n3 * one_m_cosang - dir[X]*sin_ang;
01293
01294 rot[8] = n1_n3 * one_m_cosang - dir[Y]*sin_ang;
01295 rot[9] = n2_n3 * one_m_cosang + dir[X]*sin_ang;
01296 rot[10] = n3_sq + (1.0 - n3_sq) * cos_ang;
01297
01298 bn_mat_mul( m, rot, tran1 );
01299 bn_mat_mul2( tran2, m );
01300 }
01301
01302
01303
01304
01305
01306
01307
01308 matp_t
01309 bn_mat_dup(const mat_t in)
01310 {
01311 matp_t out;
01312
01313 out = (matp_t) bu_malloc( sizeof(mat_t), "bn_mat_dup" );
01314 bcopy( (const char *)in, (char *)out, sizeof(mat_t) );
01315 return out;
01316 }
01317
01318
01319
01320
01321
01322
01323
01324
01325
01326
01327
01328 int
01329 bn_mat_ck(const char *title, const mat_t m)
01330 {
01331 vect_t A, B, C;
01332 fastf_t fx, fy, fz;
01333
01334 if( !m ) return 0;
01335
01336
01337
01338
01339
01340
01341 #if 0
01342 MAT4X3VEC( A, m, xaxis );
01343 MAT4X3VEC( B, m, yaxis );
01344 MAT4X3VEC( C, m, zaxis );
01345 #else
01346 VMOVE( A, &m[0] );
01347 VMOVE( B, &m[4] );
01348 VMOVE( C, &m[8] );
01349 #endif
01350 fx = VDOT( A, B );
01351 fy = VDOT( B, C );
01352 fz = VDOT( A, C );
01353 if( ! NEAR_ZERO(fx, 0.0001) ||
01354 ! NEAR_ZERO(fy, 0.0001) ||
01355 ! NEAR_ZERO(fz, 0.0001) ||
01356 NEAR_ZERO( m[15], VDIVIDE_TOL )
01357 ) {
01358 bu_log("bn_mat_ck(%s): bad matrix, does not preserve axis perpendicularity.\n X.Y=%g, Y.Z=%g, X.Z=%g, s=%g\n",
01359 title, fx, fy, fz, m[15] );
01360 bn_mat_print("bn_mat_ck() bad matrix", m);
01361
01362 if( bu_debug & (BU_DEBUG_MATH | BU_DEBUG_COREDUMP) ) {
01363 bu_debug |= BU_DEBUG_COREDUMP;
01364 bu_bomb("bn_mat_ck() bad matrix\n");
01365 }
01366 return -1;
01367 }
01368 return 0;
01369 }
01370
01371
01372
01373
01374
01375
01376
01377 fastf_t
01378 bn_mat_det3(const mat_t m)
01379 {
01380 FAST fastf_t sum;
01381
01382 sum = m[0] * ( m[5]*m[10] - m[6]*m[9] )
01383 -m[1] * ( m[4]*m[10] - m[6]*m[8] )
01384 +m[2] * ( m[4]*m[9] - m[5]*m[8] );
01385
01386 return( sum );
01387 }
01388
01389
01390
01391
01392
01393
01394
01395 fastf_t
01396 bn_mat_determinant(const mat_t m)
01397 {
01398 fastf_t det[4];
01399 fastf_t sum;
01400
01401 det[0] = m[5] * (m[10]*m[15] - m[11]*m[14])
01402 -m[6] * (m[ 9]*m[15] - m[11]*m[13])
01403 +m[7] * (m[ 9]*m[14] - m[10]*m[13]);
01404
01405 det[1] = m[4] * (m[10]*m[15] - m[11]*m[14])
01406 -m[6] * (m[ 8]*m[15] - m[11]*m[12])
01407 +m[7] * (m[ 8]*m[14] - m[10]*m[12]);
01408
01409 det[2] = m[4] * (m[ 9]*m[15] - m[11]*m[13])
01410 -m[5] * (m[ 8]*m[15] - m[11]*m[12])
01411 +m[7] * (m[ 8]*m[13] - m[ 9]*m[12]);
01412
01413 det[3] = m[4] * (m[ 9]*m[14] - m[10]*m[13])
01414 -m[5] * (m[ 8]*m[14] - m[10]*m[12])
01415 +m[6] * (m[ 8]*m[13] - m[ 9]*m[12]);
01416
01417 sum = m[0]*det[0] - m[1]*det[1] + m[2]*det[2] - m[3]*det[3];
01418
01419 return( sum );
01420
01421 }
01422
01423
01424
01425
01426 int
01427 bn_mat_is_non_unif(const mat_t m)
01428 {
01429 double mag[3];
01430
01431 mag[0] = MAGSQ(m);
01432 mag[1] = MAGSQ(&m[4]);
01433 mag[2] = MAGSQ(&m[8]);
01434
01435 if (fabs(1.0 - (mag[1]/mag[0])) > .0005 ||
01436 fabs(1.0 - (mag[2]/mag[0])) > .0005) {
01437
01438 return 1;
01439 }
01440
01441 if (m[12] != 0.0 || m[13] != 0.0 || m[14] != 0.0)
01442 return 2;
01443
01444 return 0;
01445 }
01446
01447
01448
01449
01450
01451
01452
01453
01454
01455