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