00001
00002
00003
00004
00005
00006
00007
00008
00009
00010
00011
00012
00013
00015
00016
00017 #include "pcl/surface/3rdparty/opennurbs/opennurbs.h"
00018
00019 static void SwapRow( double matrix[4][4], int i0, int i1 )
00020 {
00021 double* p0;
00022 double* p1;
00023 double t;
00024 p0 = &matrix[i0][0];
00025 p1 = &matrix[i1][0];
00026 t = *p0; *p0++ = *p1; *p1++ = t;
00027 t = *p0; *p0++ = *p1; *p1++ = t;
00028 t = *p0; *p0++ = *p1; *p1++ = t;
00029 t = *p0; *p0 = *p1; *p1 = t;
00030 }
00031
00032 static void SwapCol( double matrix[4][4], int j0, int j1 )
00033 {
00034 double* p0;
00035 double* p1;
00036 double t;
00037 p0 = &matrix[0][j0];
00038 p1 = &matrix[0][j1];
00039 t = *p0; *p0 = *p1; *p1 = t;
00040 p0 += 4; p1 += 4;
00041 t = *p0; *p0 = *p1; *p1 = t;
00042 p0 += 4; p1 += 4;
00043 t = *p0; *p0 = *p1; *p1 = t;
00044 p0 += 4; p1 += 4;
00045 t = *p0; *p0 = *p1; *p1 = t;
00046 }
00047
00048
00049
00050
00051
00052
00053
00054
00055
00056
00057
00058
00059
00060
00061
00062
00063
00064
00065
00066 static void AddCxRow( double matrix[4][4], double c, int i0, int i1 )
00067 {
00068 const double* p0;
00069 double* p1;
00070 p0 = &matrix[i0][0];
00071 p1 = &matrix[i1][0];
00072 *p1++ += c* *p0++;
00073 *p1++ += c* *p0++;
00074 *p1++ += c* *p0++;
00075 *p1 += c* *p0;
00076 }
00077
00078
00079
00080
00081
00082
00083
00084
00085
00086
00087
00088
00089
00090
00091
00092
00093
00094
00095 static int Inv( const double* src, double dst[4][4], double* determinant, double* pivot )
00096 {
00097
00098
00099 double M[4][4], I[4][4], x, c, d;
00100 int i, j, ix, jx;
00101 int col[4] = {0,1,2,3};
00102 int swapcount = 0;
00103 int rank = 0;
00104
00105 *pivot = 0.0;
00106 *determinant = 0.0;
00107
00108 memset( I, 0, sizeof(I) );
00109 I[0][0] = I[1][1] = I[2][2] = I[3][3] = 1.0;
00110
00111 memcpy( M, src, sizeof(M) );
00112
00113
00114
00115 ix = jx = 0;
00116 x = fabs(M[0][0]);
00117 for ( i = 0; i < 4; i++ ) for ( j = 0; j < 4; j++ ) {
00118 if ( fabs(M[i][j]) > x ) {
00119 ix = i;
00120 jx = j;
00121 x = fabs(M[i][j]);
00122 }
00123 }
00124 *pivot = x;
00125 if ( ix != 0 ) {
00126 SwapRow( M, 0, ix );
00127 SwapRow( I, 0, ix );
00128 swapcount++;
00129 }
00130 if ( jx != 0 ) {
00131 SwapCol( M, 0, jx );
00132 col[0] = jx;
00133 swapcount++;
00134 }
00135
00136 if ( x > 0.0 ) {
00137 rank++;
00138
00139
00140
00141
00142
00143
00144
00145
00146
00147 c = M[0][0];
00148 M[0][1] /= c; M[0][2] /= c; M[0][3] /= c;
00149 I[0][0] /= c; I[0][1] /= c; I[0][2] /= c; I[0][3] /= c;
00150 d = 1.0/c;
00151
00152 x *= ON_EPSILON;
00153
00154 if (fabs(M[1][0]) > x) {
00155 c = -M[1][0];
00156 M[1][1] += c*M[0][1]; M[1][2] += c*M[0][2]; M[1][3] += c*M[0][3];
00157 AddCxRow( I, c, 0, 1 );
00158 }
00159 if (fabs(M[2][0]) > x) {
00160 c = -M[2][0];
00161 M[2][1] += c*M[0][1]; M[2][2] += c*M[0][2]; M[2][3] += c*M[0][3];
00162 AddCxRow( I, c, 0, 2 );
00163 }
00164 if (fabs(M[3][0]) > x) {
00165 c = -M[3][0];
00166 M[3][1] += c*M[0][1]; M[3][2] += c*M[0][2]; M[3][3] += c*M[0][3];
00167 AddCxRow( I, c, 0, 3 );
00168 }
00169
00170 ix = jx = 1;
00171 x = fabs(M[1][1]);
00172 for ( i = 1; i < 4; i++ ) for ( j = 1; j < 4; j++ ) {
00173 if ( fabs(M[i][j]) > x ) {
00174 ix = i;
00175 jx = j;
00176 x = fabs(M[i][j]);
00177 }
00178 }
00179 if ( x < *pivot )
00180 *pivot = x;
00181 if ( ix != 1 ) {
00182 SwapRow( M, 1, ix );
00183 SwapRow( I, 1, ix );
00184 swapcount++;
00185 }
00186 if ( jx != 1 ) {
00187 SwapCol( M, 1, jx );
00188 col[1] = jx;
00189 swapcount++;
00190 }
00191 if ( x > 0.0 ) {
00192 rank++;
00193
00194
00195
00196
00197
00198
00199
00200
00201
00202
00203 c = M[1][1];
00204 M[1][2] /= c; M[1][3] /= c;
00205 I[1][0] /= c; I[1][1] /= c; I[1][2] /= c; I[1][3] /= c;
00206 d /= c;
00207
00208 x *= ON_EPSILON;
00209 if (fabs(M[0][1]) > x) {
00210 c = -M[0][1];
00211 M[0][2] += c*M[1][2]; M[0][3] += c*M[1][3];
00212 AddCxRow( I, c, 1, 0 );
00213 }
00214 if (fabs(M[2][1]) > x) {
00215 c = -M[2][1];
00216 M[2][2] += c*M[1][2]; M[2][3] += c*M[1][3];
00217 AddCxRow( I, c, 1, 2 );
00218 }
00219 if (fabs(M[3][1]) > x) {
00220 c = -M[3][1];
00221 M[3][2] += c*M[1][2]; M[3][3] += c*M[1][3];
00222 AddCxRow( I, c, 1, 3 );
00223 }
00224
00225 ix = jx = 2;
00226 x = fabs(M[2][2]);
00227 for ( i = 2; i < 4; i++ ) for ( j = 2; j < 4; j++ ) {
00228 if ( fabs(M[i][j]) > x ) {
00229 ix = i;
00230 jx = j;
00231 x = fabs(M[i][j]);
00232 }
00233 }
00234 if ( x < *pivot )
00235 *pivot = x;
00236 if ( ix != 2 ) {
00237 SwapRow( M, 2, ix );
00238 SwapRow( I, 2, ix );
00239 swapcount++;
00240 }
00241 if ( jx != 2 ) {
00242 SwapCol( M, 2, jx );
00243 col[2] = jx;
00244 swapcount++;
00245 }
00246 if ( x > 0.0 ) {
00247 rank++;
00248
00249
00250
00251
00252
00253
00254
00255
00256
00257
00258 c = M[2][2];
00259 M[2][3] /= c;
00260 I[2][0] /= c; I[2][1] /= c; I[2][2] /= c; I[2][3] /= c;
00261 d /= c;
00262
00263 x *= ON_EPSILON;
00264 if (fabs(M[0][2]) > x) {
00265 c = -M[0][2];
00266 M[0][3] += c*M[2][3];
00267 AddCxRow( I, c, 2, 0 );
00268 }
00269 if (fabs(M[1][2]) > x) {
00270 c = -M[1][2];
00271 M[1][3] += c*M[2][3];
00272 AddCxRow( I, c, 2, 1 );
00273 }
00274 if (fabs(M[3][2]) > x) {
00275 c = -M[3][2];
00276 M[3][3] += c*M[2][3];
00277 AddCxRow( I, c, 2, 3 );
00278 }
00279
00280 x = fabs(M[3][3]);
00281 if ( x < *pivot )
00282 *pivot = x;
00283
00284 if ( x > 0.0 ) {
00285 rank++;
00286
00287
00288
00289
00290
00291
00292
00293
00294
00295 c = M[3][3];
00296 I[3][0] /= c; I[3][1] /= c; I[3][2] /= c; I[3][3] /= c;
00297 d /= c;
00298
00299 x *= ON_EPSILON;
00300 if (fabs(M[0][3]) > x) {
00301 AddCxRow( I, -M[0][3], 3, 0 );
00302 }
00303 if (fabs(M[1][3]) > x) {
00304 AddCxRow( I, -M[1][3], 3, 1 );
00305 }
00306 if (fabs(M[2][3]) > x) {
00307 AddCxRow( I, -M[2][3], 3, 2 );
00308 }
00309
00310 *determinant = (swapcount%2) ? -d : d;
00311 }
00312 }
00313 }
00314 }
00315
00316 if ( col[3] != 3 )
00317 SwapRow( I, 3, col[3] );
00318 if ( col[2] != 2 )
00319 SwapRow( I, 2, col[2] );
00320 if ( col[1] != 1 )
00321 SwapRow( I, 1, col[1] );
00322 if ( col[0] != 0 )
00323 SwapRow( I, 0, col[0] );
00324
00325 memcpy( dst, I, sizeof(I) );
00326 return rank;
00327 }
00328
00330
00331
00332
00333
00334 ON_Xform::ON_Xform()
00335 {
00336 memset( m_xform, 0, sizeof(m_xform) );
00337 m_xform[3][3] = 1.0;
00338 }
00339
00340 ON_Xform::ON_Xform( int d )
00341 {
00342 memset( m_xform, 0, sizeof(m_xform) );
00343 m_xform[0][0] = m_xform[1][1] = m_xform[2][2] = (double)d;
00344 m_xform[3][3] = 1.0;
00345 }
00346
00347 ON_Xform::ON_Xform( double d )
00348 {
00349 memset( m_xform, 0, sizeof(m_xform) );
00350 m_xform[0][0] = m_xform[1][1] = m_xform[2][2] = d;
00351 m_xform[3][3] = 1.0;
00352 }
00353
00354 #if defined(ON_COMPILER_MSC)
00355 ON_Xform::ON_Xform( double m[4][4] )
00356 {
00357 memcpy( &m_xform[0][0], &m[0][0], sizeof(m_xform) );
00358 }
00359 #endif
00360
00361 ON_Xform::ON_Xform( const double m[4][4] )
00362 {
00363 memcpy( &m_xform[0][0], &m[0][0], sizeof(m_xform) );
00364 }
00365
00366 #if defined(ON_COMPILER_MSC)
00367 ON_Xform::ON_Xform( float m[4][4] )
00368 {
00369 m_xform[0][0] = (double)m[0][0];
00370 m_xform[0][1] = (double)m[0][1];
00371 m_xform[0][2] = (double)m[0][2];
00372 m_xform[0][3] = (double)m[0][3];
00373
00374 m_xform[1][0] = (double)m[1][0];
00375 m_xform[1][1] = (double)m[1][1];
00376 m_xform[1][2] = (double)m[1][2];
00377 m_xform[1][3] = (double)m[1][3];
00378
00379 m_xform[2][0] = (double)m[2][0];
00380 m_xform[2][1] = (double)m[2][1];
00381 m_xform[2][2] = (double)m[2][2];
00382 m_xform[2][3] = (double)m[2][3];
00383
00384 m_xform[3][0] = (double)m[3][0];
00385 m_xform[3][1] = (double)m[3][1];
00386 m_xform[3][2] = (double)m[3][2];
00387 m_xform[3][3] = (double)m[3][3];
00388 }
00389 #endif
00390
00391 ON_Xform::ON_Xform( const float m[4][4] )
00392 {
00393 m_xform[0][0] = (double)m[0][0];
00394 m_xform[0][1] = (double)m[0][1];
00395 m_xform[0][2] = (double)m[0][2];
00396 m_xform[0][3] = (double)m[0][3];
00397
00398 m_xform[1][0] = (double)m[1][0];
00399 m_xform[1][1] = (double)m[1][1];
00400 m_xform[1][2] = (double)m[1][2];
00401 m_xform[1][3] = (double)m[1][3];
00402
00403 m_xform[2][0] = (double)m[2][0];
00404 m_xform[2][1] = (double)m[2][1];
00405 m_xform[2][2] = (double)m[2][2];
00406 m_xform[2][3] = (double)m[2][3];
00407
00408 m_xform[3][0] = (double)m[3][0];
00409 m_xform[3][1] = (double)m[3][1];
00410 m_xform[3][2] = (double)m[3][2];
00411 m_xform[3][3] = (double)m[3][3];
00412 }
00413
00414 ON_Xform::ON_Xform( const double* m )
00415 {
00416 memcpy( &m_xform[0][0], m, sizeof(m_xform) );
00417 }
00418
00419 ON_Xform::ON_Xform( const float* m )
00420 {
00421 m_xform[0][0] = (double)m[0];
00422 m_xform[0][1] = (double)m[1];
00423 m_xform[0][2] = (double)m[2];
00424 m_xform[0][3] = (double)m[3];
00425
00426 m_xform[1][0] = (double)m[4];
00427 m_xform[1][1] = (double)m[5];
00428 m_xform[1][2] = (double)m[6];
00429 m_xform[1][3] = (double)m[7];
00430
00431 m_xform[2][0] = (double)m[8];
00432 m_xform[2][1] = (double)m[9];
00433 m_xform[2][2] = (double)m[10];
00434 m_xform[2][3] = (double)m[11];
00435
00436 m_xform[3][0] = (double)m[12];
00437 m_xform[3][1] = (double)m[13];
00438 m_xform[3][2] = (double)m[14];
00439 m_xform[3][3] = (double)m[15];
00440 }
00441
00442 ON_Xform::ON_Xform( const ON_3dPoint& P,
00443 const ON_3dVector& X,
00444 const ON_3dVector& Y,
00445 const ON_3dVector& Z)
00446 {
00447 m_xform[0][0] = X[0];
00448 m_xform[1][0] = X[1];
00449 m_xform[2][0] = X[2];
00450 m_xform[3][0] = 0;
00451
00452 m_xform[0][1] = Y[0];
00453 m_xform[1][1] = Y[1];
00454 m_xform[2][1] = Y[2];
00455 m_xform[3][1] = 0;
00456
00457 m_xform[0][2] = Z[0];
00458 m_xform[1][2] = Z[1];
00459 m_xform[2][2] = Z[2];
00460 m_xform[3][2] = 0;
00461
00462 m_xform[0][3] = P[0];
00463 m_xform[1][3] = P[1];
00464 m_xform[2][3] = P[2];
00465 m_xform[3][3] = 1;
00466 }
00467
00468 ON_Xform::ON_Xform( const ON_Matrix& m )
00469 {
00470 *this = m;
00471 }
00472
00474
00475
00476
00477
00478
00479 double* ON_Xform::operator[](int i)
00480 {
00481 return ( i >= 0 && i < 4 ) ? &m_xform[i][0] : NULL;
00482 }
00483
00484 const double* ON_Xform::operator[](int i) const
00485 {
00486 return ( i >= 0 && i < 4 ) ? &m_xform[i][0] : NULL;
00487 }
00488
00490
00491
00492
00493
00494 ON_Xform& ON_Xform::operator=( int d )
00495 {
00496 memset( m_xform, 0, sizeof(m_xform) );
00497 m_xform[0][0] = m_xform[1][1] = m_xform[2][2] = (double)d;
00498 m_xform[3][3] = 1.0;
00499 return *this;
00500 }
00501
00502 ON_Xform& ON_Xform::operator=( float d )
00503 {
00504 memset( m_xform, 0, sizeof(m_xform) );
00505 m_xform[0][0] = m_xform[1][1] = m_xform[2][2] = (double)d;
00506 m_xform[3][3] = 1.0;
00507 return *this;
00508 }
00509
00510 ON_Xform& ON_Xform::operator=( double d )
00511 {
00512 memset( m_xform, 0, sizeof(m_xform) );
00513 m_xform[0][0] = m_xform[1][1] = m_xform[2][2] = d;
00514 m_xform[3][3] = 1.0;
00515 return *this;
00516 }
00517
00519
00520
00521
00522
00523
00524 ON_Xform ON_Xform::operator*( const ON_Xform& rhs ) const
00525 {
00526 double m[4][4];
00527 const double* p = &rhs.m_xform[0][0];
00528
00529 m[0][0] = m_xform[0][0]*p[0] + m_xform[0][1]*p[4] + m_xform[0][2]*p[ 8] + m_xform[0][3]*p[12];
00530 m[0][1] = m_xform[0][0]*p[1] + m_xform[0][1]*p[5] + m_xform[0][2]*p[ 9] + m_xform[0][3]*p[13];
00531 m[0][2] = m_xform[0][0]*p[2] + m_xform[0][1]*p[6] + m_xform[0][2]*p[10] + m_xform[0][3]*p[14];
00532 m[0][3] = m_xform[0][0]*p[3] + m_xform[0][1]*p[7] + m_xform[0][2]*p[11] + m_xform[0][3]*p[15];
00533
00534 m[1][0] = m_xform[1][0]*p[0] + m_xform[1][1]*p[4] + m_xform[1][2]*p[ 8] + m_xform[1][3]*p[12];
00535 m[1][1] = m_xform[1][0]*p[1] + m_xform[1][1]*p[5] + m_xform[1][2]*p[ 9] + m_xform[1][3]*p[13];
00536 m[1][2] = m_xform[1][0]*p[2] + m_xform[1][1]*p[6] + m_xform[1][2]*p[10] + m_xform[1][3]*p[14];
00537 m[1][3] = m_xform[1][0]*p[3] + m_xform[1][1]*p[7] + m_xform[1][2]*p[11] + m_xform[1][3]*p[15];
00538
00539 m[2][0] = m_xform[2][0]*p[0] + m_xform[2][1]*p[4] + m_xform[2][2]*p[ 8] + m_xform[2][3]*p[12];
00540 m[2][1] = m_xform[2][0]*p[1] + m_xform[2][1]*p[5] + m_xform[2][2]*p[ 9] + m_xform[2][3]*p[13];
00541 m[2][2] = m_xform[2][0]*p[2] + m_xform[2][1]*p[6] + m_xform[2][2]*p[10] + m_xform[2][3]*p[14];
00542 m[2][3] = m_xform[2][0]*p[3] + m_xform[2][1]*p[7] + m_xform[2][2]*p[11] + m_xform[2][3]*p[15];
00543
00544 m[3][0] = m_xform[3][0]*p[0] + m_xform[3][1]*p[4] + m_xform[3][2]*p[ 8] + m_xform[3][3]*p[12];
00545 m[3][1] = m_xform[3][0]*p[1] + m_xform[3][1]*p[5] + m_xform[3][2]*p[ 9] + m_xform[3][3]*p[13];
00546 m[3][2] = m_xform[3][0]*p[2] + m_xform[3][1]*p[6] + m_xform[3][2]*p[10] + m_xform[3][3]*p[14];
00547 m[3][3] = m_xform[3][0]*p[3] + m_xform[3][1]*p[7] + m_xform[3][2]*p[11] + m_xform[3][3]*p[15];
00548
00549 return ON_Xform(m);
00550 }
00551
00552 ON_Xform ON_Xform::operator+( const ON_Xform& rhs ) const
00553 {
00554 double m[4][4];
00555 const double* p = &rhs.m_xform[0][0];
00556
00557 m[0][0] = m_xform[0][0] + p[0];
00558 m[0][1] = m_xform[0][1] + p[1];
00559 m[0][2] = m_xform[0][2] + p[2];
00560 m[0][3] = m_xform[0][3] + p[3];
00561
00562 m[1][0] = m_xform[1][0] + p[4];
00563 m[1][1] = m_xform[1][1] + p[5];
00564 m[1][2] = m_xform[1][2] + p[6];
00565 m[1][3] = m_xform[1][3] + p[7];
00566
00567 m[2][0] = m_xform[2][0] + p[ 8];
00568 m[2][1] = m_xform[2][1] + p[ 9];
00569 m[2][2] = m_xform[2][2] + p[10];
00570 m[2][3] = m_xform[2][3] + p[11];
00571
00572 m[3][0] = m_xform[3][0] + p[12];
00573 m[3][1] = m_xform[3][1] + p[13];
00574 m[3][2] = m_xform[3][2] + p[14];
00575 m[3][3] = m_xform[3][3] + p[15];
00576
00577 return ON_Xform(m);
00578 }
00579
00580 ON_Xform ON_Xform::operator-( const ON_Xform& rhs ) const
00581 {
00582 double m[4][4];
00583 const double* p = &rhs.m_xform[0][0];
00584
00585 m[0][0] = m_xform[0][0] - p[0];
00586 m[0][1] = m_xform[0][1] - p[1];
00587 m[0][2] = m_xform[0][2] - p[2];
00588 m[0][3] = m_xform[0][3] - p[3];
00589
00590 m[1][0] = m_xform[1][0] - p[4];
00591 m[1][1] = m_xform[1][1] - p[5];
00592 m[1][2] = m_xform[1][2] - p[6];
00593 m[1][3] = m_xform[1][3] - p[7];
00594
00595 m[2][0] = m_xform[2][0] - p[ 8];
00596 m[2][1] = m_xform[2][1] - p[ 9];
00597 m[2][2] = m_xform[2][2] - p[10];
00598 m[2][3] = m_xform[2][3] - p[11];
00599
00600 m[3][0] = m_xform[3][0] - p[12];
00601 m[3][1] = m_xform[3][1] - p[13];
00602 m[3][2] = m_xform[3][2] - p[14];
00603 m[3][3] = m_xform[3][3] - p[15];
00604
00605 return ON_Xform(m);
00606 }
00607
00609
00610
00611
00612
00613
00614 void ON_Xform::Zero()
00615 {
00616 memset( m_xform, 0, sizeof(m_xform) );
00617 }
00618
00619 void ON_Xform::Identity()
00620 {
00621 memset( m_xform, 0, sizeof(m_xform) );
00622 m_xform[0][0] = m_xform[1][1] = m_xform[2][2] = m_xform[3][3] = 1.0;
00623 }
00624
00625 void ON_Xform::Diagonal( double d )
00626 {
00627 memset( m_xform, 0, sizeof(m_xform) );
00628 m_xform[0][0] = m_xform[1][1] = m_xform[2][2] = d;
00629 m_xform[3][3] = 1.0;
00630 }
00631
00632 void ON_Xform::Scale( double x, double y, double z )
00633 {
00634 memset( m_xform, 0, sizeof(m_xform) );
00635 m_xform[0][0] = x;
00636 m_xform[1][1] = y;
00637 m_xform[2][2] = z;
00638 m_xform[3][3] = 1.0;
00639 }
00640
00641 void ON_Xform::Scale( const ON_3dVector& v )
00642 {
00643 memset( m_xform, 0, sizeof(m_xform) );
00644 m_xform[0][0] = v.x;
00645 m_xform[1][1] = v.y;
00646 m_xform[2][2] = v.z;
00647 m_xform[3][3] = 1.0;
00648 }
00649
00650 void ON_Xform::Scale
00651 (
00652 ON_3dPoint fixed_point,
00653 double scale_factor
00654 )
00655 {
00656 if ( fixed_point.x == 0.0 && fixed_point.y == 0.0 && fixed_point.z == 0.0 )
00657 {
00658 Scale( scale_factor, scale_factor, scale_factor );
00659 }
00660 else
00661 {
00662 ON_Xform t0, t1, s;
00663 t0.Translation( ON_origin - fixed_point );
00664 s.Scale( scale_factor, scale_factor, scale_factor );
00665 t1.Translation( fixed_point - ON_origin );
00666 operator=(t1*s*t0);
00667 }
00668 }
00669
00670 void ON_Xform::Scale
00671 (
00672 const ON_Plane& plane,
00673 double x_scale_factor,
00674 double y_scale_factor,
00675 double z_scale_factor
00676 )
00677 {
00678 Shear( plane, x_scale_factor*plane.xaxis, y_scale_factor*plane.yaxis, z_scale_factor*plane.zaxis );
00679 }
00680
00681 void ON_Xform::Shear
00682 (
00683 const ON_Plane& plane,
00684 const ON_3dVector& x1,
00685 const ON_3dVector& y1,
00686 const ON_3dVector& z1
00687 )
00688 {
00689 ON_Xform t0, t1, s0(1), s1(1);
00690 t0.Translation( ON_origin - plane.origin );
00691 s0.m_xform[0][0] = plane.xaxis.x;
00692 s0.m_xform[0][1] = plane.xaxis.y;
00693 s0.m_xform[0][2] = plane.xaxis.z;
00694 s0.m_xform[1][0] = plane.yaxis.x;
00695 s0.m_xform[1][1] = plane.yaxis.y;
00696 s0.m_xform[1][2] = plane.yaxis.z;
00697 s0.m_xform[2][0] = plane.zaxis.x;
00698 s0.m_xform[2][1] = plane.zaxis.y;
00699 s0.m_xform[2][2] = plane.zaxis.z;
00700 s1.m_xform[0][0] = x1.x;
00701 s1.m_xform[1][0] = x1.y;
00702 s1.m_xform[2][0] = x1.z;
00703 s1.m_xform[0][1] = y1.x;
00704 s1.m_xform[1][1] = y1.y;
00705 s1.m_xform[2][1] = y1.z;
00706 s1.m_xform[0][2] = z1.x;
00707 s1.m_xform[1][2] = z1.y;
00708 s1.m_xform[2][2] = z1.z;
00709 t1.Translation( plane.origin - ON_origin );
00710 operator=(t1*s1*s0*t0);
00711 }
00712
00713 void ON_Xform::Translation( double x, double y, double z )
00714 {
00715 Identity();
00716 m_xform[0][3] = x;
00717 m_xform[1][3] = y;
00718 m_xform[2][3] = z;
00719 m_xform[3][3] = 1.0;
00720 }
00721
00722 void ON_Xform::Translation( const ON_3dVector& v )
00723 {
00724 Identity();
00725 m_xform[0][3] = v.x;
00726 m_xform[1][3] = v.y;
00727 m_xform[2][3] = v.z;
00728 m_xform[3][3] = 1.0;
00729 }
00730
00731 void ON_Xform::PlanarProjection( const ON_Plane& plane )
00732 {
00733 int i, j;
00734 double x[3] = {plane.xaxis.x,plane.xaxis.y,plane.xaxis.z};
00735 double y[3] = {plane.yaxis.x,plane.yaxis.y,plane.yaxis.z};
00736 double p[3] = {plane.origin.x,plane.origin.y,plane.origin.z};
00737 double q[3];
00738 for ( i = 0; i < 3; i++ )
00739 {
00740 for ( j = 0; j < 3; j++ )
00741 {
00742 m_xform[i][j] = x[i]*x[j] + y[i]*y[j];
00743 }
00744 q[i] = m_xform[i][0]*p[0] + m_xform[i][1]*p[1] + m_xform[i][2]*p[2];
00745 }
00746 for ( i = 0; i < 3; i++ )
00747 {
00748 m_xform[3][i] = 0.0;
00749 m_xform[i][3] = p[i]-q[i];
00750 }
00751 m_xform[3][3] = 1.0;
00752 }
00753
00755
00756
00757
00758
00759 void ON_Xform::ActOnLeft(double x,double y,double z,double w,double v[4]) const
00760 {
00761 if ( v )
00762 {
00763 v[0] = m_xform[0][0]*x + m_xform[0][1]*y + m_xform[0][2]*z + m_xform[0][3]*w;
00764 v[1] = m_xform[1][0]*x + m_xform[1][1]*y + m_xform[1][2]*z + m_xform[1][3]*w;
00765 v[2] = m_xform[2][0]*x + m_xform[2][1]*y + m_xform[2][2]*z + m_xform[2][3]*w;
00766 v[3] = m_xform[3][0]*x + m_xform[3][1]*y + m_xform[3][2]*z + m_xform[3][3]*w;
00767 }
00768 }
00769
00770 void ON_Xform::ActOnRight(double x,double y,double z,double w,double v[4]) const
00771 {
00772 if ( v )
00773 {
00774 v[0] = m_xform[0][0]*x + m_xform[1][0]*y + m_xform[2][0]*z + m_xform[3][0]*w;
00775 v[1] = m_xform[0][1]*x + m_xform[1][1]*y + m_xform[2][1]*z + m_xform[3][1]*w;
00776 v[2] = m_xform[0][2]*x + m_xform[1][2]*y + m_xform[2][2]*z + m_xform[3][2]*w;
00777 v[3] = m_xform[0][3]*x + m_xform[1][3]*y + m_xform[2][3]*z + m_xform[3][3]*w;
00778 }
00779 }
00780
00781 ON_2dPoint ON_Xform::operator*( const ON_2dPoint& p ) const
00782 {
00783 const double x = p.x;
00784 const double y = p.y;
00785 double xh[2], w;
00786 const double* m = &m_xform[0][0];
00787 xh[0] = m[ 0]*x + m[ 1]*y + m[ 3];
00788 xh[1] = m[ 4]*x + m[ 5]*y + m[ 7];
00789 w = m[12]*x + m[13]*y + m[15];
00790 w = (w != 0.0) ? 1.0/w : 1.0;
00791 return ON_2dPoint( w*xh[0], w*xh[1] );
00792 }
00793
00794 ON_3dPoint ON_Xform::operator*( const ON_3dPoint& p ) const
00795 {
00796 const double x = p.x;
00797 const double y = p.y;
00798 const double z = p.z;
00799 double xh[3], w;
00800 const double* m = &m_xform[0][0];
00801 xh[0] = m[ 0]*x + m[ 1]*y + m[ 2]*z + m[ 3];
00802 xh[1] = m[ 4]*x + m[ 5]*y + m[ 6]*z + m[ 7];
00803 xh[2] = m[ 8]*x + m[ 9]*y + m[10]*z + m[11];
00804 w = m[12]*x + m[13]*y + m[14]*z + m[15];
00805 w = (w != 0.0) ? 1.0/w : 1.0;
00806 return ON_3dPoint( w*xh[0], w*xh[1], w*xh[2] );
00807 }
00808
00809 ON_4dPoint ON_Xform::operator*( const ON_4dPoint& h ) const
00810 {
00811 const double x = h.x;
00812 const double y = h.y;
00813 const double z = h.z;
00814 const double w = h.w;
00815 double xh[4];
00816 const double* m = &m_xform[0][0];
00817 xh[0] = m[ 0]*x + m[ 1]*y + m[ 2]*z + m[ 3]*w;
00818 xh[1] = m[ 4]*x + m[ 5]*y + m[ 6]*z + m[ 7]*w;
00819 xh[2] = m[ 8]*x + m[ 9]*y + m[10]*z + m[11]*w;
00820 xh[3] = m[12]*x + m[13]*y + m[14]*z + m[15]*w;
00821 return ON_4dPoint( xh[0],xh[1],xh[2],xh[3] );
00822 }
00823
00824 ON_2dVector ON_Xform::operator*( const ON_2dVector& v ) const
00825 {
00826 const double x = v.x;
00827 const double y = v.y;
00828 double xh[2];
00829 const double* m = &m_xform[0][0];
00830 xh[0] = m[0]*x + m[1]*y;
00831 xh[1] = m[4]*x + m[5]*y;
00832 return ON_2dVector( xh[0],xh[1] );
00833 }
00834
00835 ON_3dVector ON_Xform::operator*( const ON_3dVector& v ) const
00836 {
00837 const double x = v.x;
00838 const double y = v.y;
00839 const double z = v.z;
00840 double xh[3];
00841 const double* m = &m_xform[0][0];
00842 xh[0] = m[0]*x + m[1]*y + m[ 2]*z;
00843 xh[1] = m[4]*x + m[5]*y + m[ 6]*z;
00844 xh[2] = m[8]*x + m[9]*y + m[10]*z;
00845 return ON_3dVector( xh[0],xh[1],xh[2] );
00846 }
00847
00848 bool ON_Xform::IsValid() const
00849 {
00850 int i;
00851 const double* x = &m_xform[0][0];
00852 bool rc = true;
00853 for (i = 0; i < 16 && rc; i++)
00854 {
00855 rc = ON_IsValid(*x++);
00856 }
00857 return rc;
00858 }
00859
00860 bool ON_Xform::IsIdentity( double zero_tolerance ) const
00861 {
00862
00863
00864 const double* v = &m_xform[0][0];
00865 for ( int i = 0; i < 3; i++ )
00866 {
00867 if ( !(fabs(1.0 - *v++) <= zero_tolerance) )
00868 return false;
00869 if ( !(fabs(*v++) <= zero_tolerance) )
00870 return false;
00871 if ( !(fabs(*v++) <= zero_tolerance) )
00872 return false;
00873 if ( !(fabs(*v++) <= zero_tolerance) )
00874 return false;
00875 if ( !(fabs(*v++) <= zero_tolerance) )
00876 return false;
00877 }
00878 if ( !(fabs( 1.0 - *v ) <= zero_tolerance) )
00879 return false;
00880 return true;
00881 }
00882
00883 bool ON_Xform::IsNotIdentity( double zero_tolerance ) const
00884 {
00885
00886
00887 const double* v = &m_xform[0][0];
00888 for ( int i = 0; i < 3; i++ )
00889 {
00890 if ( fabs(1.0 - *v++) > zero_tolerance )
00891 return true;
00892 if ( fabs(*v++) > zero_tolerance )
00893 return true;
00894 if ( fabs(*v++) > zero_tolerance )
00895 return true;
00896 if ( fabs(*v++) > zero_tolerance )
00897 return true;
00898 if ( fabs(*v++) > zero_tolerance )
00899 return true;
00900 }
00901 if ( fabs( 1.0 - *v ) > zero_tolerance )
00902 return true;
00903
00904 return false;
00905 }
00906
00907 bool ON_Xform::IsTranslation( double zero_tolerance ) const
00908 {
00909 const double* v = &m_xform[0][0];
00910 if ( fabs(1.0 - *v++) > zero_tolerance )
00911 return false;
00912 if ( fabs(*v++) > zero_tolerance )
00913 return false;
00914 if ( fabs(*v++) > zero_tolerance )
00915 return false;
00916 v++;
00917 if ( fabs(*v++) > zero_tolerance )
00918 return false;
00919 if ( fabs(1.0 - *v++) > zero_tolerance )
00920 return false;
00921 if ( fabs(*v++) > zero_tolerance )
00922 return false;
00923 v++;
00924 if ( fabs(*v++) > zero_tolerance )
00925 return false;
00926 if ( fabs(*v++) > zero_tolerance )
00927 return false;
00928 if ( fabs(1.0 - *v++) > zero_tolerance )
00929 return false;
00930 v++;
00931 if ( fabs(*v++) > zero_tolerance )
00932 return false;
00933 if ( fabs(*v++) > zero_tolerance )
00934 return false;
00935 if ( fabs(*v++) > zero_tolerance )
00936 return false;
00937 if ( fabs( 1.0 - *v ) > zero_tolerance )
00938 return false;
00939 return true;
00940 }
00941
00942
00943 int ON_Xform::Compare( const ON_Xform& other ) const
00944 {
00945 const double* a = &m_xform[0][0];
00946 const double* b = &other.m_xform[0][0];
00947 int i = 16;
00948 while(i--)
00949 {
00950 if ( *a < *b )
00951 return -1;
00952 if ( *a > *b )
00953 return 1;
00954 a++;
00955 b++;
00956 }
00957 return 0;
00958 }
00959
00960 int ON_Xform::IsSimilarity() const
00961 {
00962 int rc = 0;
00963 if ( m_xform[3][0] != 0.0
00964 || m_xform[3][1] != 0.0
00965 || m_xform[3][2] != 0.0
00966 || m_xform[3][3] != 1.0 )
00967 {
00968 rc = 0;
00969 }
00970 else
00971 {
00972 double tol = 1.0e-4;
00973 double dottol = 1.0e-3;
00974 double det = Determinant();
00975 if ( fabs(det) <= ON_SQRT_EPSILON )
00976 {
00977
00978 rc = 0;
00979 }
00980 else
00981 {
00982 ON_3dVector X(m_xform[0][0],m_xform[1][0],m_xform[2][0]);
00983 ON_3dVector Y(m_xform[0][1],m_xform[1][1],m_xform[2][1]);
00984 ON_3dVector Z(m_xform[0][2],m_xform[1][2],m_xform[2][2]);
00985 double sx = X.Length();
00986 double sy = Y.Length();
00987 double sz = Z.Length();
00988 if ( sx == 0.0 || sy == 0.0 || sz == 0.0
00989 || fabs(sx-sy) > tol || fabs(sy-sz) > tol || fabs(sz-sx) > tol )
00990 {
00991
00992 rc = 0;
00993 }
00994 else
00995 {
00996 double xy = (X*Y)/(sx*sy);
00997 double yz = (Y*Z)/(sy*sz);
00998 double zx = (Z*X)/(sz*sx);
00999 if ( fabs(xy) > dottol || fabs(yz) > dottol || fabs(zx) > dottol )
01000 {
01001
01002 rc = 0;
01003 }
01004 else
01005 {
01006 rc = (det > 0.0) ? 1 : -1;
01007 }
01008 }
01009 }
01010 }
01011 return rc;
01012 }
01013
01014
01015 bool ON_Xform::IsZero() const
01016 {
01017 const double* v = &m_xform[0][0];
01018 for ( int i = 0; i < 15; i++ )
01019 {
01020 if ( *v++ != 0.0 )
01021 return false;
01022 }
01023 return true;
01024 }
01025
01026
01027 void ON_Xform::Transpose()
01028 {
01029 double t;
01030 t = m_xform[0][1]; m_xform[0][1] = m_xform[1][0]; m_xform[1][0] = t;
01031 t = m_xform[0][2]; m_xform[0][2] = m_xform[2][0]; m_xform[2][0] = t;
01032 t = m_xform[0][3]; m_xform[0][3] = m_xform[3][0]; m_xform[3][0] = t;
01033 t = m_xform[1][2]; m_xform[1][2] = m_xform[2][1]; m_xform[2][1] = t;
01034 t = m_xform[1][3]; m_xform[1][3] = m_xform[3][1]; m_xform[3][1] = t;
01035 t = m_xform[2][3]; m_xform[2][3] = m_xform[3][2]; m_xform[3][2] = t;
01036 }
01037
01038 int ON_Xform::Rank( double* pivot ) const
01039 {
01040 double I[4][4], d = 0.0, p = 0.0;
01041 int r = Inv( &m_xform[0][0], I, &d, &p );
01042 if ( pivot )
01043 *pivot = p;
01044 return r;
01045 }
01046
01047 double ON_Xform::Determinant( double* pivot ) const
01048 {
01049 double I[4][4], d = 0.0, p = 0.0;
01050
01051 Inv( &m_xform[0][0], I, &d, &p );
01052 if ( pivot )
01053 *pivot = p;
01054 if (d != 0.0 )
01055 d = 1.0/d;
01056 return d;
01057 }
01058
01059 bool ON_Xform::Invert( double* pivot )
01060 {
01061 double mrofx[4][4], d = 0.0, p = 0.0;
01062 int rank = Inv( &m_xform[0][0], mrofx, &d, &p );
01063 memcpy( m_xform, mrofx, sizeof(m_xform) );
01064 if ( pivot )
01065 *pivot = p;
01066 return (rank == 4) ? true : false;
01067 }
01068
01069 ON_Xform ON_Xform::Inverse( double* pivot ) const
01070 {
01071 ON_Xform inv;
01072 double d = 0.0, p = 0.0;
01073
01074 Inv( &m_xform[0][0], inv.m_xform, &d, &p );
01075 if ( pivot )
01076 *pivot = p;
01077 return inv;
01078 }
01079
01080 double ON_Xform::GetSurfaceNormalXform( ON_Xform& N_xform ) const
01081 {
01082
01083
01084 memcpy(&N_xform.m_xform[0][0],&m_xform[0][0], 3*sizeof(N_xform.m_xform[0][0]) );
01085 N_xform.m_xform[0][3] = 0.0;
01086 memcpy(&N_xform.m_xform[1][0],&m_xform[1][0], 3*sizeof(N_xform.m_xform[0][0]) );
01087 N_xform.m_xform[1][3] = 0.0;
01088 memcpy(&N_xform.m_xform[2][0],&m_xform[2][0], 3*sizeof(N_xform.m_xform[0][0]) );
01089 N_xform.m_xform[2][3] = 0.0;
01090 N_xform.m_xform[3][0] = 0.0;
01091 N_xform.m_xform[3][1] = 0.0;
01092 N_xform.m_xform[3][2] = 0.0;
01093 N_xform.m_xform[3][3] = 1.0;
01094
01095 double mrofx[4][4], d = 0.0, p = 0.0;
01096 double dtol = ON_SQRT_EPSILON*ON_SQRT_EPSILON*ON_SQRT_EPSILON;
01097 if ( 4 == Inv( &N_xform.m_xform[0][0], mrofx, &d, &p )
01098 && fabs(d) > dtol
01099 && fabs(d)*dtol < 1.0
01100 && fabs(p) > ON_EPSILON*fabs(d)
01101 )
01102 {
01103
01104 N_xform.m_xform[0][0] = mrofx[0][0];
01105 N_xform.m_xform[0][1] = mrofx[1][0];
01106 N_xform.m_xform[0][2] = mrofx[2][0];
01107
01108 N_xform.m_xform[1][0] = mrofx[0][1];
01109 N_xform.m_xform[1][1] = mrofx[1][1];
01110 N_xform.m_xform[1][2] = mrofx[2][1];
01111
01112 N_xform.m_xform[2][0] = mrofx[0][2];
01113 N_xform.m_xform[2][1] = mrofx[1][2];
01114 N_xform.m_xform[2][2] = mrofx[2][2];
01115 }
01116 else
01117 {
01118 d = 0.0;
01119 }
01120 return d;
01121 }
01122
01123 double ON_Xform::GetMappingXforms( ON_Xform& P_xform, ON_Xform& N_xform ) const
01124 {
01125 double d = 0.0, p = 0.0;
01126 double dtol = ON_SQRT_EPSILON*ON_SQRT_EPSILON*ON_SQRT_EPSILON;
01127 if ( 4 == Inv( &m_xform[0][0], P_xform.m_xform, &d, &p )
01128 && fabs(d) > dtol
01129 && fabs(d)*dtol < 1.0
01130 && fabs(p) > ON_EPSILON*fabs(d)
01131 )
01132 {
01133
01134 N_xform.m_xform[0][0] = m_xform[0][0];
01135 N_xform.m_xform[0][1] = m_xform[1][0];
01136 N_xform.m_xform[0][2] = m_xform[2][0];
01137 N_xform.m_xform[0][3] = 0.0;
01138
01139 N_xform.m_xform[1][0] = m_xform[0][1];
01140 N_xform.m_xform[1][1] = m_xform[1][1];
01141 N_xform.m_xform[1][2] = m_xform[2][1];
01142 N_xform.m_xform[1][3] = 0.0;
01143
01144 N_xform.m_xform[2][0] = m_xform[0][2];
01145 N_xform.m_xform[2][1] = m_xform[1][2];
01146 N_xform.m_xform[2][2] = m_xform[2][2];
01147 N_xform.m_xform[2][3] = 0.0;
01148
01149 N_xform.m_xform[3][0] = 0.0;
01150 N_xform.m_xform[3][1] = 0.0;
01151 N_xform.m_xform[3][2] = 0.0;
01152 N_xform.m_xform[3][3] = 1.0;
01153 }
01154 else
01155 {
01156 P_xform.Identity();
01157 N_xform.Identity();
01158 d = 0.0;
01159 }
01160 return d;
01161 }
01162
01163
01164 void ON_Xform::Rotation(
01165 double angle,
01166 ON_3dVector axis,
01167 ON_3dPoint center
01168 )
01169 {
01170 Rotation( sin(angle), cos(angle), axis, center );
01171 }
01172
01173 void ON_Xform::Rotation(
01174 ON_3dVector start_dir,
01175 ON_3dVector end_dir,
01176 ON_3dPoint rotation_center
01177 )
01178 {
01179 if ( fabs(start_dir.Length()-1.0) > ON_SQRT_EPSILON )
01180 start_dir.Unitize();
01181 if ( fabs(end_dir.Length()-1.0) > ON_SQRT_EPSILON )
01182 end_dir.Unitize();
01183 double cos_angle = start_dir*end_dir;
01184 ON_3dVector axis = ON_CrossProduct(start_dir,end_dir);
01185 double sin_angle = axis.Length();
01186 if ( 0.0 == sin_angle || !axis.Unitize() )
01187 {
01188 axis.PerpendicularTo(start_dir);
01189 axis.Unitize();
01190 sin_angle = 0.0;
01191 cos_angle = (cos_angle < 0.0) ? -1.0 : 1.0;
01192 }
01193 Rotation(sin_angle,cos_angle,axis,rotation_center);
01194 }
01195
01196 void ON_Xform::Rotation(
01197 double sin_angle,
01198 double cos_angle,
01199 ON_3dVector axis,
01200 ON_3dPoint center
01201 )
01202 {
01203 Identity();
01204
01205 for(;;)
01206 {
01207
01208
01209 if ( fabs(sin_angle) >= 1.0-ON_SQRT_EPSILON && fabs(cos_angle) <= ON_SQRT_EPSILON )
01210 {
01211 cos_angle = 0.0;
01212 sin_angle = (sin_angle < 0.0) ? -1.0 : 1.0;
01213 break;
01214 }
01215
01216 if ( fabs(cos_angle) >= 1.0-ON_SQRT_EPSILON && fabs(sin_angle) <= ON_SQRT_EPSILON )
01217 {
01218 cos_angle = (cos_angle < 0.0) ? -1.0 : 1.0;
01219 sin_angle = 0.0;
01220 break;
01221 }
01222
01223 if ( fabs(cos_angle*cos_angle + sin_angle*sin_angle - 1.0) > ON_SQRT_EPSILON )
01224 {
01225 ON_2dVector cs(cos_angle,sin_angle);
01226 if ( cs.Unitize() )
01227 {
01228 cos_angle = cs.x;
01229 sin_angle = cs.y;
01230
01231 }
01232 else
01233 {
01234 ON_ERROR("sin_angle and cos_angle are both zero.");
01235 cos_angle = 1.0;
01236 sin_angle = 0.0;
01237 break;
01238 }
01239 }
01240
01241 if ( fabs(cos_angle) > 1.0-ON_EPSILON || fabs(sin_angle) < ON_EPSILON )
01242 {
01243 cos_angle = (cos_angle < 0.0) ? -1.0 : 1.0;
01244 sin_angle = 0.0;
01245 break;
01246 }
01247
01248 if ( fabs(sin_angle) > 1.0-ON_EPSILON || fabs(cos_angle) < ON_EPSILON )
01249 {
01250 cos_angle = 0.0;
01251 sin_angle = (sin_angle < 0.0) ? -1.0 : 1.0;
01252 break;
01253 }
01254
01255 break;
01256 }
01257
01258 if (sin_angle != 0.0 || cos_angle != 1.0)
01259 {
01260 const double one_minus_cos_angle = 1.0 - cos_angle;
01261 ON_3dVector a = axis;
01262 if ( fabs(a.LengthSquared() - 1.0) > ON_EPSILON )
01263 a.Unitize();
01264
01265 m_xform[0][0] = a.x*a.x*one_minus_cos_angle + cos_angle;
01266 m_xform[0][1] = a.x*a.y*one_minus_cos_angle - a.z*sin_angle;
01267 m_xform[0][2] = a.x*a.z*one_minus_cos_angle + a.y*sin_angle;
01268
01269 m_xform[1][0] = a.y*a.x*one_minus_cos_angle + a.z*sin_angle;
01270 m_xform[1][1] = a.y*a.y*one_minus_cos_angle + cos_angle;
01271 m_xform[1][2] = a.y*a.z*one_minus_cos_angle - a.x*sin_angle;
01272
01273 m_xform[2][0] = a.z*a.x*one_minus_cos_angle - a.y*sin_angle;
01274 m_xform[2][1] = a.z*a.y*one_minus_cos_angle + a.x*sin_angle;
01275 m_xform[2][2] = a.z*a.z*one_minus_cos_angle + cos_angle;
01276
01277 if ( center.x != 0.0 || center.y != 0.0 || center.z != 0.0 ) {
01278 m_xform[0][3] = -((m_xform[0][0]-1.0)*center.x + m_xform[0][1]*center.y + m_xform[0][2]*center.z);
01279 m_xform[1][3] = -(m_xform[1][0]*center.x + (m_xform[1][1]-1.0)*center.y + m_xform[1][2]*center.z);
01280 m_xform[2][3] = -(m_xform[2][0]*center.x + m_xform[2][1]*center.y + (m_xform[2][2]-1.0)*center.z);
01281 }
01282
01283 m_xform[3][0] = m_xform[3][1] = m_xform[3][2] = 0.0;
01284 m_xform[3][3] = 1.0;
01285 }
01286 }
01287
01288
01289 void ON_Xform::Rotation(
01290 const ON_3dVector& X0,
01291 const ON_3dVector& Y0,
01292 const ON_3dVector& Z0,
01293 const ON_3dVector& X1,
01294 const ON_3dVector& Y1,
01295 const ON_3dVector& Z1
01296 )
01297 {
01298
01299
01300
01301 ON_Xform F0;
01302 F0[0][0] = X0.x; F0[0][1] = X0.y; F0[0][2] = X0.z;
01303 F0[1][0] = Y0.x; F0[1][1] = Y0.y; F0[1][2] = Y0.z;
01304 F0[2][0] = Z0.x; F0[2][1] = Z0.y; F0[2][2] = Z0.z;
01305 F0[3][3] = 1.0;
01306
01307
01308 ON_Xform F1;
01309 F1[0][0] = X1.x; F1[0][1] = Y1.x; F1[0][2] = Z1.x;
01310 F1[1][0] = X1.y; F1[1][1] = Y1.y; F1[1][2] = Z1.y;
01311 F1[2][0] = X1.z; F1[2][1] = Y1.z; F1[2][2] = Z1.z;
01312 F1[3][3] = 1.0;
01313
01314 *this = F1*F0;
01315 }
01316
01317 void ON_Xform::Rotation(
01318 const ON_Plane& plane0,
01319 const ON_Plane& plane1
01320 )
01321 {
01322 Rotation(
01323 plane0.origin, plane0.xaxis, plane0.yaxis, plane0.zaxis,
01324 plane1.origin, plane1.xaxis, plane1.yaxis, plane1.zaxis
01325 );
01326 }
01327
01328
01329 void ON_Xform::Rotation(
01330
01331 const ON_3dPoint& P0,
01332 const ON_3dVector& X0,
01333 const ON_3dVector& Y0,
01334 const ON_3dVector& Z0,
01335 const ON_3dPoint& P1,
01336 const ON_3dVector& X1,
01337 const ON_3dVector& Y1,
01338 const ON_3dVector& Z1
01339 )
01340 {
01341
01342
01343
01344 ON_Xform T0;
01345 T0.Translation( -P0.x, -P0.y, -P0.z );
01346
01347 ON_Xform R;
01348 R.Rotation(X0,Y0,Z0,X1,Y1,Z1);
01349
01350
01351 ON_Xform T1;
01352 T1.Translation( P1 );
01353
01354 *this = T1*R*T0;
01355 }
01356
01357 void ON_Xform::Mirror(
01358 ON_3dPoint point_on_mirror_plane,
01359 ON_3dVector normal_to_mirror_plane
01360 )
01361 {
01362 ON_3dPoint P = point_on_mirror_plane;
01363 ON_3dVector N = normal_to_mirror_plane;
01364 N.Unitize();
01365 ON_3dVector V = (2.0*(N.x*P.x + N.y*P.y + N.z*P.z))*N;
01366 m_xform[0][0] = 1 - 2.0*N.x*N.x;
01367 m_xform[0][1] = -2.0*N.x*N.y;
01368 m_xform[0][2] = -2.0*N.x*N.z;
01369 m_xform[0][3] = V.x;
01370
01371 m_xform[1][0] = -2.0*N.y*N.x;
01372 m_xform[1][1] = 1.0 -2.0*N.y*N.y;
01373 m_xform[1][2] = -2.0*N.y*N.z;
01374 m_xform[1][3] = V.y;
01375
01376 m_xform[2][0] = -2.0*N.z*N.x;
01377 m_xform[2][1] = -2.0*N.z*N.y;
01378 m_xform[2][2] = 1.0 -2.0*N.z*N.z;
01379 m_xform[2][3] = V.z;
01380
01381 m_xform[3][0] = 0.0;
01382 m_xform[3][1] = 0.0;
01383 m_xform[3][2] = 0.0;
01384 m_xform[3][3] = 1.0;
01385 }
01386
01387
01388
01389 bool ON_Xform::ChangeBasis(
01390
01391
01392
01393
01394
01395
01396
01397
01398 const ON_Plane& plane0,
01399 const ON_Plane& plane1
01400 )
01401 {
01402 return ChangeBasis(
01403 plane0.origin, plane0.xaxis, plane0.yaxis, plane0.zaxis,
01404 plane1.origin, plane1.xaxis, plane1.yaxis, plane1.zaxis
01405 );
01406 }
01407
01408
01409 bool ON_Xform::ChangeBasis(
01410 const ON_3dVector& X0,
01411 const ON_3dVector& Y0,
01412 const ON_3dVector& Z0,
01413 const ON_3dVector& X1,
01414 const ON_3dVector& Y1,
01415 const ON_3dVector& Z1
01416 )
01417 {
01418
01419
01420
01421 Zero();
01422 m_xform[3][3] = 1.0;
01423 double a,b,c,d;
01424 a = X1*Y1;
01425 b = X1*Z1;
01426 c = Y1*Z1;
01427 double R[3][6] = {{X1*X1, a, b, X1*X0, X1*Y0, X1*Z0},
01428 { a, Y1*Y1, c, Y1*X0, Y1*Y0, Y1*Z0},
01429 { b, c, Z1*Z1, Z1*X0, Z1*Y0, Z1*Z0}};
01430
01431
01432
01433
01434
01435 int i0 = (R[0][0] >= R[1][1]) ? 0 : 1;
01436 if ( R[2][2] > R[i0][i0] )
01437 i0 = 2;
01438 int i1 = (i0+1)%3;
01439 int i2 = (i1+1)%3;
01440 if ( R[i0][i0] == 0.0 )
01441 return false;
01442 d = 1.0/R[i0][i0];
01443 R[i0][0] *= d;
01444 R[i0][1] *= d;
01445 R[i0][2] *= d;
01446 R[i0][3] *= d;
01447 R[i0][4] *= d;
01448 R[i0][5] *= d;
01449 R[i0][i0] = 1.0;
01450 if ( R[i1][i0] != 0.0 ) {
01451 d = -R[i1][i0];
01452 R[i1][0] += d*R[i0][0];
01453 R[i1][1] += d*R[i0][1];
01454 R[i1][2] += d*R[i0][2];
01455 R[i1][3] += d*R[i0][3];
01456 R[i1][4] += d*R[i0][4];
01457 R[i1][5] += d*R[i0][5];
01458 R[i1][i0] = 0.0;
01459 }
01460 if ( R[i2][i0] != 0.0 ) {
01461 d = -R[i2][i0];
01462 R[i2][0] += d*R[i0][0];
01463 R[i2][1] += d*R[i0][1];
01464 R[i2][2] += d*R[i0][2];
01465 R[i2][3] += d*R[i0][3];
01466 R[i2][4] += d*R[i0][4];
01467 R[i2][5] += d*R[i0][5];
01468 R[i2][i0] = 0.0;
01469 }
01470
01471 if ( fabs(R[i1][i1]) < fabs(R[i2][i2]) ) {
01472 int i = i1; i1 = i2; i2 = i;
01473 }
01474 if ( R[i1][i1] == 0.0 )
01475 return false;
01476 d = 1.0/R[i1][i1];
01477 R[i1][0] *= d;
01478 R[i1][1] *= d;
01479 R[i1][2] *= d;
01480 R[i1][3] *= d;
01481 R[i1][4] *= d;
01482 R[i1][5] *= d;
01483 R[i1][i1] = 1.0;
01484 if ( R[i0][i1] != 0.0 ) {
01485 d = -R[i0][i1];
01486 R[i0][0] += d*R[i1][0];
01487 R[i0][1] += d*R[i1][1];
01488 R[i0][2] += d*R[i1][2];
01489 R[i0][3] += d*R[i1][3];
01490 R[i0][4] += d*R[i1][4];
01491 R[i0][5] += d*R[i1][5];
01492 R[i0][i1] = 0.0;
01493 }
01494 if ( R[i2][i1] != 0.0 ) {
01495 d = -R[i2][i1];
01496 R[i2][0] += d*R[i1][0];
01497 R[i2][1] += d*R[i1][1];
01498 R[i2][2] += d*R[i1][2];
01499 R[i2][3] += d*R[i1][3];
01500 R[i2][4] += d*R[i1][4];
01501 R[i2][5] += d*R[i1][5];
01502 R[i2][i1] = 0.0;
01503 }
01504
01505 if ( R[i2][i2] == 0.0 )
01506 return false;
01507 d = 1.0/R[i2][i2];
01508 R[i2][0] *= d;
01509 R[i2][1] *= d;
01510 R[i2][2] *= d;
01511 R[i2][3] *= d;
01512 R[i2][4] *= d;
01513 R[i2][5] *= d;
01514 R[i2][i2] = 1.0;
01515 if ( R[i0][i2] != 0.0 ) {
01516 d = -R[i0][i2];
01517 R[i0][0] += d*R[i2][0];
01518 R[i0][1] += d*R[i2][1];
01519 R[i0][2] += d*R[i2][2];
01520 R[i0][3] += d*R[i2][3];
01521 R[i0][4] += d*R[i2][4];
01522 R[i0][5] += d*R[i2][5];
01523 R[i0][i2] = 0.0;
01524 }
01525 if ( R[i1][i2] != 0.0 ) {
01526 d = -R[i1][i2];
01527 R[i1][0] += d*R[i2][0];
01528 R[i1][1] += d*R[i2][1];
01529 R[i1][2] += d*R[i2][2];
01530 R[i1][3] += d*R[i2][3];
01531 R[i1][4] += d*R[i2][4];
01532 R[i1][5] += d*R[i2][5];
01533 R[i1][i2] = 0.0;
01534 }
01535
01536 m_xform[0][0] = R[0][3];
01537 m_xform[0][1] = R[0][4];
01538 m_xform[0][2] = R[0][5];
01539
01540 m_xform[1][0] = R[1][3];
01541 m_xform[1][1] = R[1][4];
01542 m_xform[1][2] = R[1][5];
01543
01544 m_xform[2][0] = R[2][3];
01545 m_xform[2][1] = R[2][4];
01546 m_xform[2][2] = R[2][5];
01547
01548 return true;
01549 }
01550
01551 bool ON_Xform::ChangeBasis(
01552 const ON_3dPoint& P0,
01553 const ON_3dVector& X0,
01554 const ON_3dVector& Y0,
01555 const ON_3dVector& Z0,
01556 const ON_3dPoint& P1,
01557 const ON_3dVector& X1,
01558 const ON_3dVector& Y1,
01559 const ON_3dVector& Z1
01560 )
01561 {
01562 bool rc = false;
01563
01564
01565
01566 ON_Xform F0(P0,X0,Y0,Z0);
01567
01568
01569 ON_Xform T1;
01570 T1.Translation( -P1.x, -P1.y, -P1.z );
01571
01572 ON_Xform CB;
01573 rc = CB.ChangeBasis(ON_xaxis, ON_yaxis, ON_zaxis,X1,Y1,Z1);
01574
01575 *this = CB*T1*F0;
01576 return rc;
01577 }
01578
01579 void ON_Xform::WorldToCamera(
01580 const ON_3dPoint& cameraLocation,
01581 const ON_3dVector& cameraX,
01582 const ON_3dVector& cameraY,
01583 const ON_3dVector& cameraZ
01584 )
01585 {
01586
01587
01588 m_xform[0][0] = cameraX.x; m_xform[0][1] = cameraX.y; m_xform[0][2] = cameraX.z;
01589 m_xform[0][3] = -(cameraX.x*cameraLocation.x + cameraX.y*cameraLocation.y + cameraX.z*cameraLocation.z);
01590 m_xform[1][0] = cameraY.x; m_xform[1][1] = cameraY.y; m_xform[1][2] = cameraY.z;
01591 m_xform[1][3] = -(cameraY.x*cameraLocation.x + cameraY.y*cameraLocation.y + cameraY.z*cameraLocation.z);
01592 m_xform[2][0] = cameraZ.x; m_xform[2][1] = cameraZ.y; m_xform[2][2] = cameraZ.z;
01593 m_xform[2][3] = -(cameraZ.x*cameraLocation.x + cameraZ.y*cameraLocation.y + cameraZ.z*cameraLocation.z);
01594 m_xform[3][0] = m_xform[3][1] = m_xform[3][2] = 0.0; m_xform[3][3] = 1.0;
01595 }
01596
01597 void ON_Xform::CameraToWorld(
01598 const ON_3dPoint& cameraLocation,
01599 const ON_3dVector& cameraX,
01600 const ON_3dVector& cameraY,
01601 const ON_3dVector& cameraZ
01602 )
01603 {
01604
01605
01606 m_xform[0][0] = cameraX.x; m_xform[0][1] = cameraY.x; m_xform[0][2] = cameraZ.x;
01607 m_xform[0][3] = cameraLocation.x;
01608 m_xform[1][0] = cameraX.y; m_xform[1][1] = cameraY.y; m_xform[1][2] = cameraZ.y;
01609 m_xform[1][3] = cameraLocation.y;
01610 m_xform[2][0] = cameraX.z; m_xform[2][1] = cameraY.z; m_xform[2][2] = cameraZ.z;
01611 m_xform[2][3] = cameraLocation.z;
01612 m_xform[3][0] = m_xform[3][1] = m_xform[3][2] = 0.0; m_xform[3][3] = 1.0;
01613 }
01614
01615 bool ON_Xform::CameraToClip(
01616 ON_BOOL32 bPerspective,
01617 double left, double right,
01618 double bottom, double top,
01619 double near_dist, double far_dist
01620 )
01621 {
01622 double dd;
01623
01624 if ( left == right || bottom == top || near_dist == far_dist )
01625 return false;
01626
01627 if ( !bPerspective ) {
01628
01629
01630
01631
01632
01633
01634
01635
01636
01637 dd = (left-right);
01638 m_xform[0][0] = -2.0/dd; m_xform[0][3] = (left+right)/dd; m_xform[0][1] = m_xform[0][2] = 0.0;
01639 dd = (bottom-top);
01640 m_xform[1][1] = -2.0/dd; m_xform[1][3] = (bottom+top)/dd; m_xform[1][0] = m_xform[1][2] = 0.0;
01641 dd = (far_dist-near_dist);
01642 m_xform[2][2] = 2.0/dd; m_xform[2][3] = (far_dist+near_dist)/dd; m_xform[2][0] = m_xform[2][1] = 0.0;
01643 m_xform[3][0] = m_xform[3][1] = m_xform[3][2] = 0.0; m_xform[3][3] = 1.0;
01644 }
01645 else
01646 {
01647
01648
01649
01650
01651
01652
01653
01654
01655
01656
01657
01658
01659
01660
01661
01662
01663
01664
01665
01666
01667
01668
01669
01670
01671
01672
01673
01674
01675
01676
01677
01678
01679
01680
01681 dd = (right-left);
01682 m_xform[0][0] = 2.0*near_dist/dd;
01683 m_xform[0][2] = (right+left)/dd;
01684 m_xform[0][1] = m_xform[0][3] = 0.0;
01685
01686 dd = (top-bottom);
01687 m_xform[1][1] = 2.0*near_dist/dd;
01688 m_xform[1][2] = (top+bottom)/dd;
01689 m_xform[1][0] = m_xform[1][3] = 0.0;
01690
01691 dd = (far_dist-near_dist);
01692 m_xform[2][2] = (far_dist+near_dist)/dd;
01693 m_xform[2][3] = 2.0*near_dist*far_dist/dd;
01694 m_xform[2][0] = m_xform[2][1] = 0.0;
01695
01696 m_xform[3][0] = m_xform[3][1] = m_xform[3][3] = 0.0; m_xform[3][2] = -1.0;
01697 }
01698 return true;
01699 }
01700
01701 bool ON_Xform::ClipToCamera(
01702 ON_BOOL32 bPerspective,
01703 double left, double right,
01704 double bottom, double top,
01705 double near_dist, double far_dist
01706 )
01707 {
01708
01709 double dd;
01710 if ( left == right || bottom == top || near_dist == far_dist )
01711 return false;
01712
01713 if ( !bPerspective ) {
01714
01715 m_xform[0][0] = 0.5*(right-left); m_xform[0][3] = 0.5*(right+left); m_xform[0][1] = m_xform[0][2] = 0.0;
01716 m_xform[1][1] = 0.5*(top-bottom); m_xform[1][3] = 0.5*(top+bottom); m_xform[1][0] = m_xform[1][2] = 0.0;
01717 m_xform[2][2] = 0.5*(far_dist-near_dist); m_xform[2][3] = -0.5*(far_dist+near_dist); m_xform[2][0] = m_xform[2][1] = 0.0;
01718 m_xform[3][0] = m_xform[3][1] = m_xform[3][2] = 0.0; m_xform[3][3] = 1.0;
01719 }
01720 else {
01721
01722
01723
01724
01725
01726
01727
01728
01729
01730
01731
01732
01733
01734
01735
01736
01737
01738
01739
01740
01741
01742 dd = 2.0*near_dist;
01743 m_xform[0][0] = (right-left)/dd;
01744 m_xform[0][3] = (right+left)/dd;
01745 m_xform[0][1] = m_xform[0][2] = 0.0;
01746
01747 m_xform[1][1] = (top-bottom)/dd;
01748 m_xform[1][3] = (top+bottom)/dd;
01749 m_xform[1][0] = m_xform[1][2] = 0.0;
01750
01751 m_xform[2][0] = m_xform[2][1] = m_xform[2][2] = 0.0; m_xform[2][3] = -1.0;
01752
01753 dd *= far_dist;
01754 m_xform[3][2] = (far_dist-near_dist)/dd;
01755 m_xform[3][3] = (far_dist+near_dist)/dd;
01756 m_xform[3][0] = m_xform[3][1] = 0.0;
01757 }
01758
01759 return true;
01760 }
01761
01762 bool ON_Xform::ClipToScreen(
01763 double left, double right,
01764 double bottom, double top,
01765 double near_z, double far_z
01766 )
01767 {
01768
01769 if ( left == right || bottom == top )
01770 return false;
01771
01772 m_xform[0][0] = 0.5*(right-left);
01773 m_xform[0][3] = 0.5*(right+left);
01774 m_xform[0][1] = m_xform[0][2] = 0.0;
01775
01776 m_xform[1][1] = 0.5*(top-bottom);
01777 m_xform[1][3] = 0.5*(top+bottom);
01778 m_xform[1][0] = m_xform[1][2] = 0.0;
01779
01780 if (far_z != near_z) {
01781 m_xform[2][2] = 0.5*(near_z-far_z);
01782 m_xform[2][3] = 0.5*(near_z+far_z);
01783 }
01784 else {
01785 m_xform[2][2] = 1.0;
01786 m_xform[2][3] = 0.0;
01787 }
01788 m_xform[2][0] = m_xform[2][1] = 0.0;
01789
01790 m_xform[3][0] = m_xform[3][1] = m_xform[3][2] = 0.0;
01791 m_xform[3][3] = 1.0;
01792
01793 return true;
01794 }
01795
01796 bool ON_Xform::ScreenToClip(
01797 double left, double right,
01798 double bottom, double top,
01799 double near_z, double far_z
01800 )
01801 {
01802
01803 ON_Xform c2s;
01804 bool rc = c2s.ClipToScreen( left, right, bottom, top, near_z, far_z );
01805 if (rc) {
01806 m_xform[0][0] = 1.0/c2s[0][0]; m_xform[0][3] = -c2s[0][3]/c2s[0][0];
01807 m_xform[0][1] = m_xform[0][2] = 0.0;
01808
01809 m_xform[1][1] = 1.0/c2s[1][1]; m_xform[1][3] = -c2s[1][3]/c2s[1][1];
01810 m_xform[1][0] = m_xform[1][2] = 0.0;
01811
01812 m_xform[2][2] = 1.0/c2s[2][2]; m_xform[2][3] = -c2s[2][3]/c2s[2][2];
01813 m_xform[2][0] = m_xform[2][1] = 0.0;
01814
01815 m_xform[3][0] = m_xform[3][1] = m_xform[3][2] = 0.0;
01816 m_xform[3][3] = 1.0;
01817 }
01818 return rc;
01819 }
01820
01821
01822 int ON_Xform::ClipFlag4d( const double* point ) const
01823 {
01824 if ( !point )
01825 return 1|2|4|8|16|32;
01826 int clip = 0;
01827 double x = m_xform[0][0]*point[0] + m_xform[0][1]*point[1] + m_xform[0][2]*point[2] + m_xform[0][3]*point[3];
01828 double y = m_xform[1][0]*point[0] + m_xform[1][1]*point[1] + m_xform[1][2]*point[2] + m_xform[1][3]*point[3];
01829 double z = m_xform[2][0]*point[0] + m_xform[2][1]*point[1] + m_xform[2][2]*point[2] + m_xform[2][3]*point[3];
01830 double w = m_xform[3][0]*point[0] + m_xform[3][1]*point[1] + m_xform[3][2]*point[2] + m_xform[3][3]*point[3];
01831 if ( point[3] < 0.0 ) {
01832 x = -x; y = -y; z = -z; w = -w;
01833 }
01834 if ( x <= -w )
01835 clip |= 1;
01836 else if ( x >= w )
01837 clip |= 2;
01838 if ( y <= -w )
01839 clip |= 4;
01840 else if ( y >= w )
01841 clip |= 8;
01842 if ( z <= -w )
01843 clip |= 16;
01844 else if ( z >= w )
01845 clip |= 32;
01846 return clip;
01847 }
01848
01849 int ON_Xform::ClipFlag3d( const double* point ) const
01850 {
01851 if ( !point )
01852 return 1|2|4|8|16|32;
01853 int clip = 0;
01854 const double x = m_xform[0][0]*point[0] + m_xform[0][1]*point[1] + m_xform[0][2]*point[2] + m_xform[0][3];
01855 const double y = m_xform[1][0]*point[0] + m_xform[1][1]*point[1] + m_xform[1][2]*point[2] + m_xform[1][3];
01856 const double z = m_xform[2][0]*point[0] + m_xform[2][1]*point[1] + m_xform[2][2]*point[2] + m_xform[2][3];
01857 const double w = m_xform[3][0]*point[0] + m_xform[3][1]*point[1] + m_xform[3][2]*point[2] + m_xform[3][3];
01858 if ( x <= -w )
01859 clip |= 1;
01860 else if ( x >= w )
01861 clip |= 2;
01862 if ( y <= -w )
01863 clip |= 4;
01864 else if ( y >= w )
01865 clip |= 8;
01866 if ( z <= -w )
01867 clip |= 16;
01868 else if ( z >= w )
01869 clip |= 32;
01870 return clip;
01871 }
01872
01873 int ON_Xform::ClipFlag4d( int count, int stride, const double* point,
01874 ON_BOOL32 bTestZ ) const
01875 {
01876 int clip = 1|2|4|8;
01877 if ( bTestZ)
01878 clip |= (16|32);
01879 if ( point && ((count > 0 && stride >= 4) || count == 1) ) {
01880 for ( ; clip && count--; point += stride ) {
01881 clip &= ClipFlag4d( point );
01882 }
01883 }
01884 return clip;
01885 }
01886
01887 int ON_Xform::ClipFlag3d( int count, int stride, const double* point,
01888 ON_BOOL32 bTestZ ) const
01889 {
01890 int clip = 1|2|4|8;
01891 if ( bTestZ)
01892 clip |= (16|32);
01893 if ( point && ((count > 0 && stride >= 3) || count == 1) ) {
01894 for ( ; clip && count--; point += stride ) {
01895 clip &= ClipFlag3d( point );
01896 }
01897 }
01898 return clip;
01899 }
01900
01901 int ON_Xform::ClipFlag3dBox( const double* boxmin, const double* boxmax ) const
01902 {
01903 int clip = 1|2|4|8|16|32;
01904 double point[3];
01905 int i,j,k;
01906 if ( boxmin && boxmax ) {
01907 for (i=0;i<2;i++) {
01908 point[0] = (i)?boxmax[0]:boxmin[0];
01909 for (j=0;j<2;j++) {
01910 point[1] = (j)?boxmax[1]:boxmin[1];
01911 for (k=0;k<2;k++) {
01912 point[2] = (k)?boxmax[2]:boxmin[2];
01913 clip &= ClipFlag3d(point);
01914 if ( !clip )
01915 return 0;
01916 }
01917 }
01918 }
01919 }
01920 return clip;
01921 }
01922
01923 ON_Xform& ON_Xform::operator=(const ON_Matrix& src)
01924 {
01925 int i,j;
01926 i = src.RowCount();
01927 const int maxi = (i>4)?4:i;
01928 j = src.ColCount();
01929 const int maxj = (j>4)?4:j;
01930 Identity();
01931 for ( i = 0; i < maxi; i++ ) for ( j = 0; j < maxj; j++ ) {
01932 m_xform[i][j] = src.m[i][j];
01933 }
01934 return *this;
01935 }
01936
01937 bool ON_Xform::IntervalChange(
01938 int dir,
01939 ON_Interval old_interval,
01940 ON_Interval new_interval
01941 )
01942 {
01943 bool rc = false;
01944 Identity();
01945 if ( dir >= 0
01946 && dir <= 3
01947 && old_interval[0] != ON_UNSET_VALUE
01948 && old_interval[1] != ON_UNSET_VALUE
01949 && new_interval[0] != ON_UNSET_VALUE
01950 && new_interval[1] != ON_UNSET_VALUE
01951 && old_interval.Length() != 0.0
01952 )
01953 {
01954 rc = true;
01955 if ( new_interval != old_interval )
01956 {
01957 double s = new_interval.Length()/old_interval.Length();;
01958 double d = (new_interval[0]*old_interval[1] - new_interval[1]*old_interval[0])/old_interval.Length();
01959 m_xform[dir][dir] = s;
01960 m_xform[dir][3] = d;
01961 }
01962 }
01963 return rc;
01964 }