00001
00002 #ifdef VCL_NEEDS_PRAGMA_INTERFACE
00003 #pragma implementation
00004 #endif
00005
00006
00007
00008 #include "PMatrixDecompCR.h"
00009
00010
00011 #include <vcl_iostream.h>
00012
00013 #include <vnl/vnl_matlab_print.h>
00014 #include <vnl/vnl_double_3.h>
00015 #include <vnl/algo/vnl_qr.h>
00016
00017 #include <mvl/PMatrix.h>
00018
00019 PMatrixDecompCR::PMatrixDecompCR(const PMatrix& P, bool scale_C)
00020 {
00021 compute(P.get_matrix(), scale_C);
00022 }
00023
00024 PMatrixDecompCR::PMatrixDecompCR(const vnl_double_3x4& P, bool scale_C)
00025 {
00026 compute(P, scale_C);
00027 }
00028
00029 void UtSolve(const vnl_double_3x3& T, vnl_double_3& x)
00030 {
00031 x[2] /= T(2,2);
00032 x[1] = (x[1] - T(1,2)*x[2])/T(1,1);
00033 x[0] = (x[0] - T(0,1)*x[1] - T(0,2)*x[2])/T(0,0);
00034 }
00035
00036
00037 void PMatrixDecompCR::compute(const vnl_double_3x4& p, bool scale_C)
00038 {
00039
00040
00041 vnl_double_3x3 PermHtPerm;
00042
00043 for (int i = 0; i < 3; ++i)
00044 for (int j = 0; j < 3; ++j)
00045 PermHtPerm(i,j) = p(2-j,2-i);
00046
00047 vnl_qr<double> qr(PermHtPerm.as_ref());
00048
00049 vnl_double_3x3 Q = qr.Q();
00050 vnl_double_3x3 R = qr.R();
00051
00052
00053
00054 int r0pos = R(0,0) > 0 ? 1 : 0;
00055 int r1pos = R(1,1) > 0 ? 1 : 0;
00056 int r2pos = R(2,2) > 0 ? 1 : 0;
00057 typedef double d3[3];
00058 d3 diags[] = {
00059 { -1, 1, -1},
00060 { 1, -1, -1},
00061 { -1, -1, -1},
00062 { 1, 1, -1},
00063 { -1, -1, 1},
00064 { 1, 1, 1},
00065 { -1, 1, 1},
00066 { 1, -1, 1},
00067 };
00068 int d = r0pos * 4 + r1pos * 2 + r2pos;
00069 double* diag = &diags[d][0];
00070
00071 for (int i = 0; i < 3; ++i)
00072 for (int j = 0; j < 3; ++j) {
00073 C(j,i) = diag[i] * R(2-i,2-j);
00074 Po(j,i) = diag[j] * Q(2-i,2-j);
00075 }
00076
00077
00078 vnl_double_3 t;
00079 for (int i = 0; i < 3; ++i)
00080 t[i] = p(i,3);
00081 UtSolve(C, t);
00082
00083 for (int i = 0; i < 3; ++i)
00084 Po(i,3) = t[i];
00085
00086 if (((C * Po - p).fro_norm() > 1e-4) ||
00087 (C(0,0) < 0) ||
00088 (C(1,1) < 0) ||
00089 (C(2,2) < 0)) {
00090 vcl_cerr << "PMatrixDecompCR: AIEEE!\n";
00091 vnl_matlab_print(vcl_cerr, p, "p");
00092 vnl_matlab_print(vcl_cerr, C, "C");
00093 vnl_matlab_print(vcl_cerr, Po, "Po");
00094 vnl_matlab_print(vcl_cerr, C * Po - p, "C * Po - p");
00095 }
00096
00097
00098 if (scale_C)
00099 C *= 1.0/C(2,2);
00100 }