00001
00002 #ifdef VCL_NEEDS_PRAGMA_INTERFACE
00003 #pragma implementation
00004 #endif
00005
00006
00007
00008
00009 #include "osl_ortho_regress.h"
00010 #include <vcl_cmath.h>
00011 #include <vcl_cassert.h>
00012
00013
00014
00015 void osl_ortho_regress::add_points(double const *x, double const *y, unsigned n) {
00016 for (unsigned i=0; i<n; ++i)
00017 add_point(x[i], y[i]);
00018 }
00019
00020 void osl_ortho_regress::add_points(float const *x, float const *y, unsigned n) {
00021 for (unsigned i=0; i<n; ++i)
00022 add_point(x[i], y[i]);
00023 }
00024
00025 double osl_ortho_regress::rms_cost(double a, double b, double c) const {
00026 return vcl_sqrt( cost(a, b, c) / S1 );
00027 }
00028
00029
00030
00031
00032 #include <vnl/algo/vnl_symmetric_eigensystem.h>
00033
00034
00035
00036
00037
00038
00039
00040 static
00041 bool symmetric_2x2_eigen_system(double a, double b, double c,
00042 double *xmin, double *ymin, double *lmin,
00043 double *xmax, double *ymax, double *lmax)
00044 {
00045 vnl_matrix<double> M(2, 2);
00046 M(0, 0) = a;
00047 M(0, 1) = M(1, 0) = b;
00048 M(1, 1) = c;
00049 vnl_symmetric_eigensystem<double> sym(M);
00050 if (xmin) *xmin = sym.V(0, 0);
00051 if (ymin) *ymin = sym.V(1, 0);
00052 if (lmin) *lmin = sym.D(0, 0);
00053
00054 if (xmax) *xmax = sym.V(0, 1);
00055 if (ymax) *ymax = sym.V(1, 1);
00056 if (lmax) *lmax = sym.D(1, 1);
00057
00058 return true;
00059 }
00060
00061
00062
00063
00064
00065
00066
00067
00068
00069
00070
00071
00072
00073
00074
00075 double osl_ortho_regress::cost(double a, double b, double c) const {
00076 return
00077 (Sxx*a*a + 2*Sxy*a*b + Syy*b*b + 2*Sx*a*c + 2*Sy*b*c + S1*c*c)/(a*a+b*b);
00078 }
00079
00080 bool osl_ortho_regress::fit(double &a, double &b, double &c) const {
00081 assert(S1 >= 2);
00082 double xbar = Sx/S1;
00083 double ybar = Sy/S1;
00084
00085 if (!symmetric_2x2_eigen_system(Sxx-Sx*Sx/S1, Sxy-Sx*Sy/S1, Syy-Sy*Sy/S1,
00086 &a, &b, 0,
00087 0, 0, 0))
00088 return false;
00089
00090 c = -(a*xbar+b*ybar);
00091 return true;
00092 }
00093
00094
00095
00096
00097
00098
00099
00100
00101
00102
00103
00104
00105
00106
00107 bool osl_ortho_regress::fit_constrained(double x, double y,
00108 double &a, double &b, double &c) const
00109 {
00110 assert(S1 >= 1);
00111
00112 if (!symmetric_2x2_eigen_system(Sxx-2*Sx*x+S1*x*x, Sxy-Sx*y-x*Sy+S1*x*y, Syy-2*Sy*y+S1*y*y,
00113 &a, &b, 0,
00114 0, 0, 0))
00115 return false;
00116
00117 c = -(a*x + b*y);
00118 return true;
00119 }