/* Numerical functions for computing minimizers of a least-squares system of equations. Copyright (C) 2011 Scott Schaefer This library is free software; you can redistribute it and/or modify it under the terms of the GNU Lesser General Public License (LGPL) as published by the Free Software Foundation; either version 2.1 of the License, or (at your option) any later version. This library is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU Lesser General Public License for more details. You should have received a copy of the GNU Lesser General Public License along with this library; if not, write to the Free Software Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA */ #include "eigen.h" #include #include #include #include #define ROTATE(a,i,j,k,l) g=a[i][j];h=a[k][l];a[i][j]=g-s*(h+g*tau);a[k][l]=h+s*(g-h*tau); int method = 3; // for reducing two upper triangular systems of equations into 1 void qr ( float *mat1, float *mat2, float *rvalue ) { int i, j; float temp1 [ 8 ] [ 4 ]; for ( i = 0; i < 4; i++ ) { for ( j = 0; j < i; j++ ) { temp1 [ i ] [ j ] = 0; temp1 [ i + 4 ] [ j ] = 0; } for ( j = i; j < 4; j++ ) { temp1 [ i ] [ j ] = mat1 [ ( 7 * i - i * i ) / 2 + j ]; temp1 [ i + 4 ] [ j ] = mat2 [ ( 7 * i - i * i ) / 2 + j ]; } } qr ( temp1, 8, rvalue ); } // WARNING: destroys eqs in the process void qr ( float eqs[][4], int num, float *rvalue ) { int i, j, k; qr ( eqs, num, 0.000001f ); for ( i = 0; i < 10; i++ ) { rvalue [ i ] = 0; } k = 0; for ( i = 0; i < num && i < 4; i++ ) { for ( j = i; j < 4; j++ ) { rvalue [ k++ ] = eqs [ i ] [ j ]; } } } void qr ( float eqs[][4], int num, float tol ) { int i, j, k; float a, b, mag, temp; for ( i = 0; i < 4 && i < num; i++ ) { for ( j = i + 1; j < num; j++ ) { a = eqs [ i ] [ i ]; b = eqs [ j ] [ i ]; if ( fabs ( a ) > 0.000001f || fabs ( b ) > 0.000001f ) { mag = (float)sqrt ( a * a + b * b ); a /= mag; b /= mag; for ( k = 0; k < 4; k++ ) { temp = a * eqs [ i ] [ k ] + b * eqs [ j ] [ k ]; eqs [ j ] [ k ] = b * eqs [ i ] [ k ] - a * eqs [ j ] [ k ]; eqs [ i ] [ k ] = temp; } } } for ( j = i - 1; j >= 0; j-- ) { if ( eqs [ j ] [ j ] < 0.000001f && eqs [ j ] [ j ] > -0.000001f ) { a = eqs [ i ] [ i ]; b = eqs [ j ] [ i ]; if ( fabs ( a ) > 0.000001f || fabs ( b ) > 0.000001f ) { mag = (float)sqrt ( a * a + b * b ); a /= mag; b /= mag; for ( k = 0; k < 4; k++ ) { temp = a * eqs [ i ] [ k ] + b * eqs [ j ] [ k ]; eqs [ j ] [ k ] = b * eqs [ i ] [ k ] - a * eqs [ j ] [ k ]; eqs [ i ] [ k ] = temp; } } } } } } void jacobi ( float u[][3], float d[], float v[][3] ) { int j, iq, ip, i; float tresh, theta, tau, t, sm, s, h, g, c, b [ 3 ], z [ 3 ]; float a [ 3 ] [ 3 ]; a [ 0 ] [ 0 ] = u [ 0 ] [ 0 ]; a [ 0 ] [ 1 ] = u [ 0 ] [ 1 ]; a [ 0 ] [ 2 ] = u [ 0 ] [ 2 ]; a [ 1 ] [ 0 ] = u [ 1 ] [ 0 ]; a [ 1 ] [ 1 ] = u [ 1 ] [ 1 ]; a [ 1 ] [ 2 ] = u [ 1 ] [ 2 ]; a [ 2 ] [ 0 ] = u [ 2 ] [ 0 ]; a [ 2 ] [ 1 ] = u [ 2 ] [ 1 ]; a [ 2 ] [ 2 ] = u [ 2 ] [ 2 ]; for ( ip = 0; ip < 3; ip++ ) { for ( iq = 0; iq < 3; iq++ ) { v [ ip ] [ iq ] = 0.0f; } v [ ip ] [ ip ] = 1.0f; } for ( ip = 0; ip < 3; ip++ ) { b [ ip ] = a [ ip ] [ ip ]; d [ ip ] = b [ ip ]; z [ ip ] = 0.0f; } for ( i = 1; i <= 50; i++ ) { sm = 0.0f; for ( ip = 0; ip < 2; ip++ ) { for ( iq = ip + 1; iq < 3; iq++ ) { sm += (float)fabs ( a [ ip ] [ iq ] ); } } if ( sm == 0.0f ) { // sort the stupid things and transpose a [ 0 ] [ 0 ] = v [ 0 ] [ 0 ]; a [ 0 ] [ 1 ] = v [ 1 ] [ 0 ]; a [ 0 ] [ 2 ] = v [ 2 ] [ 0 ]; a [ 1 ] [ 0 ] = v [ 0 ] [ 1 ]; a [ 1 ] [ 1 ] = v [ 1 ] [ 1 ]; a [ 1 ] [ 2 ] = v [ 2 ] [ 1 ]; a [ 2 ] [ 0 ] = v [ 0 ] [ 2 ]; a [ 2 ] [ 1 ] = v [ 1 ] [ 2 ]; a [ 2 ] [ 2 ] = v [ 2 ] [ 2 ]; if ( fabs ( d [ 0 ] ) < fabs ( d [ 1 ] ) ) { sm = d [ 0 ]; d [ 0 ] = d [ 1 ]; d [ 1 ] = sm; sm = a [ 0 ] [ 0 ]; a [ 0 ] [ 0 ] = a [ 1 ] [ 0 ]; a [ 1 ] [ 0 ] = sm; sm = a [ 0 ] [ 1 ]; a [ 0 ] [ 1 ] = a [ 1 ] [ 1 ]; a [ 1 ] [ 1 ] = sm; sm = a [ 0 ] [ 2 ]; a [ 0 ] [ 2 ] = a [ 1 ] [ 2 ]; a [ 1 ] [ 2 ] = sm; } if ( fabs ( d [ 1 ] ) < fabs ( d [ 2 ] ) ) { sm = d [ 1 ]; d [ 1 ] = d [ 2 ]; d [ 2 ] = sm; sm = a [ 1 ] [ 0 ]; a [ 1] [ 0 ] = a [ 2 ] [ 0 ]; a [ 2 ] [ 0 ] = sm; sm = a [ 1 ] [ 1 ]; a [ 1 ] [ 1 ] = a [ 2 ] [ 1 ]; a [ 2 ] [ 1 ] = sm; sm = a [ 1 ] [ 2 ]; a [ 1 ] [ 2 ] = a [ 2 ] [ 2 ]; a [ 2 ] [ 2 ] = sm; } if ( fabs ( d [ 0 ] ) < fabs ( d [ 1 ] ) ) { sm = d [ 0 ]; d [ 0 ] = d [ 1 ]; d [ 1 ] = sm; sm = a [ 0 ] [ 0 ]; a [ 0 ] [ 0 ] = a [ 1 ] [ 0 ]; a [ 1 ] [ 0 ] = sm; sm = a [ 0 ] [ 1 ]; a [ 0 ] [ 1 ] = a [ 1 ] [ 1 ]; a [ 1 ] [ 1 ] = sm; sm = a [ 0 ] [ 2 ]; a [ 0 ] [ 2 ] = a [ 1 ] [ 2 ]; a [ 1 ] [ 2 ] = sm; } v [ 0 ] [ 0 ] = a [ 0 ] [ 0 ]; v [ 0 ] [ 1 ] = a [ 0 ] [ 1 ]; v [ 0 ] [ 2 ] = a [ 0 ] [ 2 ]; v [ 1 ] [ 0 ] = a [ 1 ] [ 0 ]; v [ 1 ] [ 1 ] = a [ 1 ] [ 1 ]; v [ 1 ] [ 2 ] = a [ 1 ] [ 2 ]; v [ 2 ] [ 0 ] = a [ 2 ] [ 0 ]; v [ 2 ] [ 1 ] = a [ 2 ] [ 1 ]; v [ 2 ] [ 2 ] = a [ 2 ] [ 2 ]; return; } if ( i < 4 ) { tresh = 0.2f * sm / 9; } else { tresh = 0.0f; } for ( ip = 0; ip < 2; ip++ ) { for ( iq = ip + 1; iq < 3; iq++ ) { g = 100.0f * (float)fabs ( a [ ip ] [ iq ] ); if ( i > 4 && (float)( fabs ( d [ ip ] ) + g ) == (float)fabs ( d [ ip ] ) && (float)( fabs ( d [ iq ] ) + g ) == (float)fabs ( d [ iq ] ) ) { a [ ip ] [ iq ] = 0.0f; } else { if ( fabs ( a [ ip ] [ iq ] ) > tresh ) { h = d [ iq ] - d [ ip ]; if ( (float)( fabs ( h ) + g ) == (float)fabs ( h ) ) { t = ( a [ ip ] [ iq ] ) / h; } else { theta = 0.5f * h / ( a [ ip ] [ iq ] ); t = 1.0f / ( (float)fabs ( theta ) + (float)sqrt ( 1.0f + theta * theta ) ); if ( theta < 0.0f ) { t = -1.0f * t; } } c = 1.0f / (float)sqrt ( 1 + t * t ); s = t * c; tau = s / ( 1.0f + c ); h = t * a [ ip ] [ iq ]; z [ ip ] -= h; z [ iq ] += h; d [ ip ] -= h; d [ iq ] += h; a [ ip ] [ iq ] = 0.0f; for ( j = 0; j <= ip - 1; j++ ) { ROTATE ( a, j, ip, j, iq ) } for ( j = ip + 1; j <= iq - 1; j++ ) { ROTATE ( a, ip, j, j, iq ) } for ( j = iq + 1; j < 3; j++ ) { ROTATE ( a, ip, j, iq, j ) } for ( j = 0; j < 3; j++ ) { ROTATE ( v, j, ip, j, iq ) } } } } } for ( ip = 0; ip < 3; ip++ ) { b [ ip ] += z [ ip ]; d [ ip ] = b [ ip ]; z [ ip ] = 0.0f; } } printf ( "too many iterations in jacobi\n" ); exit ( 1 ); } int estimateRank ( float *a ) { float w [ 3 ]; float u [ 3 ] [ 3 ]; float mat [ 3 ] [ 3 ]; int i; mat [ 0 ] [ 0 ] = a [ 0 ]; mat [ 0 ] [ 1 ] = a [ 1 ]; mat [ 0 ] [ 2 ] = a [ 2 ]; mat [ 1 ] [ 1 ] = a [ 3 ]; mat [ 1 ] [ 2 ] = a [ 4 ]; mat [ 2 ] [ 2 ] = a [ 5 ]; mat [ 1 ] [ 0 ] = a [ 1 ]; mat [ 2 ] [ 0 ] = a [ 2 ]; mat [ 2 ] [ 1 ] = a [ 4 ]; jacobi ( mat, w, u ); if ( w [ 0 ] == 0.0f ) { return 0; } else { for ( i = 1; i < 3; i++ ) { if ( w [ i ] < 0.1f ) { return i; } } return 3; } } void matInverse ( float mat[][3], float midpoint[], float rvalue[][3], float w[], float u[][3] ) { // there is an implicit assumption that mat is symmetric and real // U and V in the SVD will then be the same matrix whose rows are the eigenvectors of mat // W will just be the eigenvalues of mat // float w [ 3 ]; // float u [ 3 ] [ 3 ]; int i; jacobi ( mat, w, u ); if ( w [ 0 ] == 0.0f ) { // printf ( "error: largest eigenvalue is 0!\n" ); } else { for ( i = 1; i < 3; i++ ) { if ( w [ i ] < 0.001f ) // / w [ 0 ] < TOLERANCE ) { w [ i ] = 0; } else { w [ i ] = 1.0f / w [ i ]; } } w [ 0 ] = 1.0f / w [ 0 ]; } rvalue [ 0 ] [ 0 ] = w [ 0 ] * u [ 0 ] [ 0 ] * u [ 0 ] [ 0 ] + w [ 1 ] * u [ 1 ] [ 0 ] * u [ 1 ] [ 0 ] + w [ 2 ] * u [ 2 ] [ 0 ] * u [ 2 ] [ 0 ]; rvalue [ 0 ] [ 1 ] = w [ 0 ] * u [ 0 ] [ 0 ] * u [ 0 ] [ 1 ] + w [ 1 ] * u [ 1 ] [ 0 ] * u [ 1 ] [ 1 ] + w [ 2 ] * u [ 2 ] [ 0 ] * u [ 2 ] [ 1 ]; rvalue [ 0 ] [ 2 ] = w [ 0 ] * u [ 0 ] [ 0 ] * u [ 0 ] [ 2 ] + w [ 1 ] * u [ 1 ] [ 0 ] * u [ 1 ] [ 2 ] + w [ 2 ] * u [ 2 ] [ 0 ] * u [ 2 ] [ 2 ]; rvalue [ 1 ] [ 0 ] = w [ 0 ] * u [ 0 ] [ 1 ] * u [ 0 ] [ 0 ] + w [ 1 ] * u [ 1 ] [ 1 ] * u [ 1 ] [ 0 ] + w [ 2 ] * u [ 2 ] [ 1 ] * u [ 2 ] [ 0 ]; rvalue [ 1 ] [ 1 ] = w [ 0 ] * u [ 0 ] [ 1 ] * u [ 0 ] [ 1 ] + w [ 1 ] * u [ 1 ] [ 1 ] * u [ 1 ] [ 1 ] + w [ 2 ] * u [ 2 ] [ 1 ] * u [ 2 ] [ 1 ]; rvalue [ 1 ] [ 2 ] = w [ 0 ] * u [ 0 ] [ 1 ] * u [ 0 ] [ 2 ] + w [ 1 ] * u [ 1 ] [ 1 ] * u [ 1 ] [ 2 ] + w [ 2 ] * u [ 2 ] [ 1 ] * u [ 2 ] [ 2 ]; rvalue [ 2 ] [ 0 ] = w [ 0 ] * u [ 0 ] [ 2 ] * u [ 0 ] [ 0 ] + w [ 1 ] * u [ 1 ] [ 2 ] * u [ 1 ] [ 0 ] + w [ 2 ] * u [ 2 ] [ 2 ] * u [ 2 ] [ 0 ]; rvalue [ 2 ] [ 1 ] = w [ 0 ] * u [ 0 ] [ 2 ] * u [ 0 ] [ 1 ] + w [ 1 ] * u [ 1 ] [ 2 ] * u [ 1 ] [ 1 ] + w [ 2 ] * u [ 2 ] [ 2 ] * u [ 2 ] [ 1 ]; rvalue [ 2 ] [ 2 ] = w [ 0 ] * u [ 0 ] [ 2 ] * u [ 0 ] [ 2 ] + w [ 1 ] * u [ 1 ] [ 2 ] * u [ 1 ] [ 2 ] + w [ 2 ] * u [ 2 ] [ 2 ] * u [ 2 ] [ 2 ]; } float calcError ( float a[][3], float b[], float btb, float point[] ) { float rvalue = btb; rvalue += -2.0f * ( point [ 0 ] * b [ 0 ] + point [ 1 ] * b [ 1 ] + point [ 2 ] * b [ 2 ] ); rvalue += point [ 0 ] * ( a [ 0 ] [ 0 ] * point [ 0 ] + a [ 0 ] [ 1 ] * point [ 1 ] + a [ 0 ] [ 2 ] * point [ 2 ] ); rvalue += point [ 1 ] * ( a [ 1 ] [ 0 ] * point [ 0 ] + a [ 1 ] [ 1 ] * point [ 1 ] + a [ 1 ] [ 2 ] * point [ 2 ] ); rvalue += point [ 2 ] * ( a [ 2 ] [ 0 ] * point [ 0 ] + a [ 2 ] [ 1 ] * point [ 1 ] + a [ 2 ] [ 2 ] * point [ 2 ] ); return rvalue; } float *calcNormal ( float halfA[], float norm[], float expectedNorm[] ) { /* float a [ 3 ] [ 3 ]; float w [ 3 ]; float u [ 3 ] [ 3 ]; a [ 0 ] [ 0 ] = halfA [ 0 ]; a [ 0 ] [ 1 ] = halfA [ 1 ]; a [ 0 ] [ 2 ] = halfA [ 2 ]; a [ 1 ] [ 1 ] = halfA [ 3 ]; a [ 1 ] [ 2 ] = halfA [ 4 ]; a [ 1 ] [ 0 ] = halfA [ 1 ]; a [ 2 ] [ 0 ] = halfA [ 2 ]; a [ 2 ] [ 1 ] = halfA [ 4 ]; a [ 2 ] [ 2 ] = halfA [ 5 ]; jacobi ( a, w, u ); if ( u [ 1 ] != 0 ) { if ( w [ 1 ] / w [ 0 ] > 0.2f ) { // two dominant eigen values, just return the expectedNorm norm [ 0 ] = expectedNorm [ 0 ]; norm [ 1 ] = expectedNorm [ 1 ]; norm [ 2 ] = expectedNorm [ 2 ]; return; } } norm [ 0 ] = u [ 0 ] [ 0 ]; norm [ 1 ] = u [ 0 ] [ 1 ]; norm [ 2 ] = u [ 0 ] [ 2 ]; */ float dot = norm [ 0 ] * expectedNorm [ 0 ] + norm [ 1 ] * expectedNorm [ 1 ] + norm [ 2 ] * expectedNorm [ 2 ]; if ( dot < 0 ) { norm [ 0 ] *= -1.0f; norm [ 1 ] *= -1.0f; norm [ 2 ] *= -1.0f; dot *= -1.0f; } if ( dot < 0.707f ) { return expectedNorm; } else { return norm; } } void descent ( float A[][3], float B[], float guess[], BoundingBoxf *box ) { int i; float r [ 3 ]; float delta, delta0; int n = 10; float alpha, div; float newPoint [ 3 ]; float c; float store [ 3 ]; store [ 0 ] = guess [ 0 ]; store [ 1 ] = guess [ 1 ]; store [ 2 ] = guess [ 2 ]; if ( method == 2 || method == 0 ) { i = 0; r [ 0 ] = B [ 0 ] - ( A [ 0 ] [ 0 ] * guess [ 0 ] + A [ 0 ] [ 1 ] * guess [ 1 ] + A [ 0 ] [ 2 ] * guess [ 2 ] ); r [ 1 ] = B [ 1 ] - ( A [ 1 ] [ 0 ] * guess [ 0 ] + A [ 1 ] [ 1 ] * guess [ 1 ] + A [ 1 ] [ 2 ] * guess [ 2 ] ); r [ 2 ] = B [ 2 ] - ( A [ 2 ] [ 0 ] * guess [ 0 ] + A [ 2 ] [ 1 ] * guess [ 1 ] + A [ 2 ] [ 2 ] * guess [ 2 ] ); delta = r [ 0 ] * r [ 0 ] + r [ 1 ] * r [ 1 ] + r [ 2 ] * r [ 2 ]; delta0 = delta * TOLERANCE * TOLERANCE; while ( i < n && delta > delta0 ) { div = r [ 0 ] * ( A [ 0 ] [ 0 ] * r [ 0 ] + A [ 0 ] [ 1 ] * r [ 1 ] + A [ 0 ] [ 2 ] * r [ 2 ] ); div += r [ 1 ] * ( A [ 1 ] [ 0 ] * r [ 0 ] + A [ 1 ] [ 1 ] * r [ 1 ] + A [ 1 ] [ 2 ] * r [ 2 ] ); div += r [ 2 ] * ( A [ 2 ] [ 0 ] * r [ 0 ] + A [ 2 ] [ 1 ] * r [ 1 ] + A [ 2 ] [ 2 ] * r [ 2 ] ); if ( fabs ( div ) < 0.0000001f ) { break; } alpha = delta / div; newPoint [ 0 ] = guess [ 0 ] + alpha * r [ 0 ]; newPoint [ 1 ] = guess [ 1 ] + alpha * r [ 1 ]; newPoint [ 2 ] = guess [ 2 ] + alpha * r [ 2 ]; guess [ 0 ] = newPoint [ 0 ]; guess [ 1 ] = newPoint [ 1 ]; guess [ 2 ] = newPoint [ 2 ]; r [ 0 ] = B [ 0 ] - ( A [ 0 ] [ 0 ] * guess [ 0 ] + A [ 0 ] [ 1 ] * guess [ 1 ] + A [ 0 ] [ 2 ] * guess [ 2 ] ); r [ 1 ] = B [ 1 ] - ( A [ 1 ] [ 0 ] * guess [ 0 ] + A [ 1 ] [ 1 ] * guess [ 1 ] + A [ 1 ] [ 2 ] * guess [ 2 ] ); r [ 2 ] = B [ 2 ] - ( A [ 2 ] [ 0 ] * guess [ 0 ] + A [ 2 ] [ 1 ] * guess [ 1 ] + A [ 2 ] [ 2 ] * guess [ 2 ] ); delta = r [ 0 ] * r [ 0 ] + r [ 1 ] * r [ 1 ] + r [ 2 ] * r [ 2 ]; i++; } if ( guess [ 0 ] >= box->begin.x && guess [ 0 ] <= box->end.x && guess [ 1 ] >= box->begin.y && guess [ 1 ] <= box->end.y && guess [ 2 ] >= box->begin.z && guess [ 2 ] <= box->end.z ) { return; } } if ( method == 0 || method == 1 ) { c = A [ 0 ] [ 0 ] + A [ 1 ] [ 1 ] + A [ 2 ] [ 2 ]; if ( c == 0 ) { return; } c = ( 0.75f / c ); guess [ 0 ] = store [ 0 ]; guess [ 1 ] = store [ 1 ]; guess [ 2 ] = store [ 2 ]; r [ 0 ] = B [ 0 ] - ( A [ 0 ] [ 0 ] * guess [ 0 ] + A [ 0 ] [ 1 ] * guess [ 1 ] + A [ 0 ] [ 2 ] * guess [ 2 ] ); r [ 1 ] = B [ 1 ] - ( A [ 1 ] [ 0 ] * guess [ 0 ] + A [ 1 ] [ 1 ] * guess [ 1 ] + A [ 1 ] [ 2 ] * guess [ 2 ] ); r [ 2 ] = B [ 2 ] - ( A [ 2 ] [ 0 ] * guess [ 0 ] + A [ 2 ] [ 1 ] * guess [ 1 ] + A [ 2 ] [ 2 ] * guess [ 2 ] ); for ( i = 0; i < n; i++ ) { guess [ 0 ] = guess [ 0 ] + c * r [ 0 ]; guess [ 1 ] = guess [ 1 ] + c * r [ 1 ]; guess [ 2 ] = guess [ 2 ] + c * r [ 2 ]; r [ 0 ] = B [ 0 ] - ( A [ 0 ] [ 0 ] * guess [ 0 ] + A [ 0 ] [ 1 ] * guess [ 1 ] + A [ 0 ] [ 2 ] * guess [ 2 ] ); r [ 1 ] = B [ 1 ] - ( A [ 1 ] [ 0 ] * guess [ 0 ] + A [ 1 ] [ 1 ] * guess [ 1 ] + A [ 1 ] [ 2 ] * guess [ 2 ] ); r [ 2 ] = B [ 2 ] - ( A [ 2 ] [ 0 ] * guess [ 0 ] + A [ 2 ] [ 1 ] * guess [ 1 ] + A [ 2 ] [ 2 ] * guess [ 2 ] ); } } /* if ( guess [ 0 ] > store [ 0 ] + 1 || guess [ 0 ] < store [ 0 ] - 1 || guess [ 1 ] > store [ 1 ] + 1 || guess [ 1 ] < store [ 1 ] - 1 || guess [ 2 ] > store [ 2 ] + 1 || guess [ 2 ] < store [ 2 ] - 1 ) { printf ( "water let point go from %f,%f,%f to %f,%f,%f\n", store [ 0 ], store [ 1 ], store [ 2 ], guess [ 0 ], guess [ 1 ], guess [ 2 ] ); printf ( "A is %f,%f,%f %f,%f,%f %f,%f,%f\n", A [ 0 ] [ 0 ], A [ 0 ] [ 1 ], A [ 0 ] [ 2 ], A [ 1 ] [ 0 ] , A [ 1 ] [ 1 ], A [ 1 ] [ 2 ], A [ 2 ] [ 0 ], A [ 2 ] [ 1 ], A [ 2 ] [ 2 ] ); printf ( "B is %f,%f,%f\n", B [ 0 ], B [ 1 ], B [ 2 ] ); printf ( "bounding box is %f,%f,%f to %f,%f,%f\n", box->begin.x, box->begin.y, box->begin.z, box->end.x, box->end.y, box->end.z ); } */ } float calcPoint ( float halfA[], float b[], float btb, float midpoint[], float rvalue[], BoundingBoxf *box, float *mat ) { float newB [ 3 ]; float a [ 3 ] [ 3 ]; float inv [ 3 ] [ 3 ]; float w [ 3 ]; float u [ 3 ] [ 3 ]; a [ 0 ] [ 0 ] = halfA [ 0 ]; a [ 0 ] [ 1 ] = halfA [ 1 ]; a [ 0 ] [ 2 ] = halfA [ 2 ]; a [ 1 ] [ 1 ] = halfA [ 3 ]; a [ 1 ] [ 2 ] = halfA [ 4 ]; a [ 1 ] [ 0 ] = halfA [ 1 ]; a [ 2 ] [ 0 ] = halfA [ 2 ]; a [ 2 ] [ 1 ] = halfA [ 4 ]; a [ 2 ] [ 2 ] = halfA [ 5 ]; switch ( method ) { case 0: case 1: case 2: rvalue [ 0 ] = midpoint [ 0 ]; rvalue [ 1 ] = midpoint [ 1 ]; rvalue [ 2 ] = midpoint [ 2 ]; descent ( a, b, rvalue, box ); return calcError ( a, b, btb, rvalue ); break; case 3: matInverse ( a, midpoint, inv, w, u ); newB [ 0 ] = b [ 0 ] - a [ 0 ] [ 0 ] * midpoint [ 0 ] - a [ 0 ] [ 1 ] * midpoint [ 1 ] - a [ 0 ] [ 2 ] * midpoint [ 2 ]; newB [ 1 ] = b [ 1 ] - a [ 1 ] [ 0 ] * midpoint [ 0 ] - a [ 1 ] [ 1 ] * midpoint [ 1 ] - a [ 1 ] [ 2 ] * midpoint [ 2 ]; newB [ 2 ] = b [ 2 ] - a [ 2 ] [ 0 ] * midpoint [ 0 ] - a [ 2 ] [ 1 ] * midpoint [ 1 ] - a [ 2 ] [ 2 ] * midpoint [ 2 ]; rvalue [ 0 ] = inv [ 0 ] [ 0 ] * newB [ 0 ] + inv [ 1 ] [ 0 ] * newB [ 1 ] + inv [ 2 ] [ 0 ] * newB [ 2 ] + midpoint [ 0 ]; rvalue [ 1 ] = inv [ 0 ] [ 1 ] * newB [ 0 ] + inv [ 1 ] [ 1 ] * newB [ 1 ] + inv [ 2 ] [ 1 ] * newB [ 2 ] + midpoint [ 1 ]; rvalue [ 2 ] = inv [ 0 ] [ 2 ] * newB [ 0 ] + inv [ 1 ] [ 2 ] * newB [ 1 ] + inv [ 2 ] [ 2 ] * newB [ 2 ] + midpoint [ 2 ]; return calcError ( a, b, btb, rvalue ); break; case 4: method = 3; calcPoint ( halfA, b, btb, midpoint, rvalue, box, mat ); method = 4; /* int rank; float eqs [ 4 ] [ 4 ]; // form the square matrix eqs [ 0 ] [ 0 ] = mat [ 0 ]; eqs [ 0 ] [ 1 ] = mat [ 1 ]; eqs [ 0 ] [ 2 ] = mat [ 2 ]; eqs [ 0 ] [ 3 ] = mat [ 3 ]; eqs [ 1 ] [ 1 ] = mat [ 4 ]; eqs [ 1 ] [ 2 ] = mat [ 5 ]; eqs [ 1 ] [ 3 ] = mat [ 6 ]; eqs [ 2 ] [ 2 ] = mat [ 7 ]; eqs [ 2 ] [ 3 ] = mat [ 8 ]; eqs [ 3 ] [ 3 ] = mat [ 9 ]; eqs [ 1 ] [ 0 ] = eqs [ 2 ] [ 0 ] = eqs [ 2 ] [ 1 ] = eqs [ 3 ] [ 0 ] = eqs [ 3 ] [ 1 ] = eqs [ 3 ] [ 2 ] = 0; // compute the new QR decomposition and rank rank = qr ( eqs ); method = 2; calcPoint ( halfA, b, btb, midpoint, rvalue, box, mat ); method = 4; if ( rank == 0 ) { // it's zero, no equations rvalue [ 0 ] = midpoint [ 0 ]; rvalue [ 1 ] = midpoint [ 1 ]; rvalue [ 2 ] = midpoint [ 2 ]; } else { if ( rank == 1 ) { // one equation, it's a plane float temp = ( eqs [ 0 ] [ 0 ] * midpoint [ 0 ] + eqs [ 0 ] [ 1 ] * midpoint [ 1 ] + eqs [ 0 ] [ 2 ] * midpoint [ 2 ] - eqs [ 0 ] [ 3 ] ) / ( eqs [ 0 ] [ 0 ] * eqs [ 0 ] [ 0 ] + eqs [ 0 ] [ 1 ] * eqs [ 0 ] [ 1 ] + eqs [ 0 ] [ 2 ] * eqs [ 0 ] [ 2 ] ); rvalue [ 0 ] = midpoint [ 0 ] - temp * eqs [ 0 ] [ 0 ]; rvalue [ 1 ] = midpoint [ 1 ] - temp * eqs [ 0 ] [ 1 ]; rvalue [ 2 ] = midpoint [ 2 ] - temp * eqs [ 0 ] [ 2 ]; } else { if ( rank == 2 ) { // two equations, it's a line float a, b, c, d, e, f, g; // reduce back to upper triangular qr ( eqs, 2, 0.000001f ); a = eqs [ 0 ] [ 0 ]; b = eqs [ 0 ] [ 1 ]; c = eqs [ 0 ] [ 2 ]; d = eqs [ 0 ] [ 3 ]; e = eqs [ 1 ] [ 1 ]; f = eqs [ 1 ] [ 2 ]; g = eqs [ 1 ] [ 3 ]; // solved using the equations // ax + by + cz = d // ey + fz = g // minimize (x-px)^2 + (y-py)^2 + (z-pz)^2 if ( a > 0.000001f || a < -0.000001f ) { if ( e > 0.00000f || e < -0.000001f ) { rvalue [ 2 ] = ( -1 * b * d * e * f + ( a * a + b * b ) * g * f + c * e * ( d * e - b * g ) + a * e * ( ( b * f - c * e ) * midpoint [ 0 ] - a * f * midpoint [ 1 ] + a * e * midpoint [ 2 ] ) ) / ( a * a * ( e * e + f * f ) + ( c * e - b * f ) * ( c * e - b * f ) ); rvalue [ 1 ] = ( g - f * rvalue [ 2 ] ) / e; rvalue [ 0 ] = ( d - b * rvalue [ 1 ] - c * rvalue [ 2 ] ) / a; } else { // slightly degenerate case where e==0 rvalue [ 2 ] = g / f; rvalue [ 1 ] = ( b * d * f - b * c * g - a * b * f * midpoint [ 0 ] + a * a * f * midpoint [ 1 ] ) / ( a * a * f + b * b * f ); rvalue [ 0 ] = ( d - b * rvalue [ 1 ] - c * rvalue [ 2 ] ) / a; } } else { // degenerate case where a==0 so e == 0 (upper triangular) rvalue [ 2 ] = g / f; rvalue [ 1 ] = ( d - c * rvalue [ 2 ] ) / b; rvalue [ 0 ] = midpoint [ 0 ]; } } else { // must be three equations or more now... solve using back-substitution rvalue [ 2 ] = mat [ 8 ] / mat [ 7 ]; rvalue [ 1 ] = ( mat [ 6 ] - mat [ 5 ] * rvalue [ 2 ] ) / mat [ 4 ]; rvalue [ 0 ] = ( mat [ 3 ] - mat [ 2 ] * rvalue [ 2 ] - mat [ 1 ] * rvalue [ 1 ] ) / mat [ 0 ]; } } } */ float ret; float tmp; ret = mat [ 9 ] * mat [ 9 ]; tmp = mat [ 0 ] * rvalue [ 0 ] + mat [ 1 ] * rvalue [ 1 ] + mat [ 2 ] * rvalue [ 2 ] - mat [ 3 ]; ret += tmp * tmp; tmp = mat [ 4 ] * rvalue [ 1 ] + mat [ 5 ] * rvalue [ 2 ] - mat [ 6 ]; ret += tmp * tmp; tmp = mat [ 7 ] * rvalue [ 2 ] - mat [ 8 ]; ret += tmp * tmp; return ret; break; case 5: rvalue [ 0 ] = midpoint [ 0 ]; rvalue [ 1 ] = midpoint [ 1 ]; rvalue [ 2 ] = midpoint [ 2 ]; return calcError ( a, b, btb, rvalue ); } return 0 ; }