contrib/brl/bbas/bsta/bsta_kent.txx
Go to the documentation of this file.
00001 #ifndef bsta_kent_txx_
00002 #define bsta_kent_txx_
00003 
00004 #include "bsta_kent.h"
00005 #include <vnl/vnl_vector.h>
00006 #include <vnl/vnl_matrix.h>
00007 #include <vnl/vnl_bessel.h>
00008 #include <vnl/vnl_gamma.h>
00009 #include <vnl/vnl_math.h>
00010 #include <vnl/algo/vnl_symmetric_eigensystem.h>
00011 #include <vnl/io/vnl_io_vector_fixed.h>
00012 #if 0
00013 #include <vnl/vnl_inverse.h>
00014 #include <vgl/vgl_plane_3d.h>
00015 #include <vgl/vgl_vector_3d.h>
00016 #endif
00017 #include <vcl_cassert.h>
00018 
00019 template <class T>
00020 bsta_kent<T>::bsta_kent(vnl_matrix_fixed<T,3,3> const& m)
00021 {
00022   vnl_symmetric_eigensystem<T> E(m.as_ref());
00023   T t3 = E.get_eigenvalue(0); // smallest ??
00024   T t2 = E.get_eigenvalue(1);
00025   T t1 = E.get_eigenvalue(2); // largest??
00026 
00027   assert(t1 > t3);
00028 
00029   gamma3_ = E.get_eigenvector(0);  // check if this is the smallest values's vector
00030   gamma2_ = E.get_eigenvector(1);
00031   gamma1_ = E.get_eigenvector(2);
00032 
00033   vcl_cout << "gamma1->" << gamma1_ << vcl_endl
00034            << "gamma2->" << gamma2_ << vcl_endl
00035            << "gamma3->" << gamma3_ << vcl_endl;
00036 
00037   // compute the kent distr. parameters
00038   vnl_matrix<T> g3(3,1);
00039   g3.put(0,0,gamma3_.get(0));
00040   g3.put(1,0,gamma3_.get(1));
00041   g3.put(2,0,gamma3_.get(2));
00042   vnl_matrix<T> g3t = g3.transpose();
00043   vnl_matrix<T> res=(g3t*m*g3);
00044   // make sure that res is 1x1
00045   T R = 1 - res.get(0,0);
00046   T Q = vcl_abs(t3-t2);
00047 
00048   kappa_= (1./(2.-2.*R-Q))+(1./(2.-2.*R+Q)); // always >= 0
00049   beta_= 0.5 * kappa_;
00050   vcl_cout << "kappa=" << kappa_ << "beta=" << beta_ << vcl_endl;
00051 }
00052 
00053 #if 0
00054 template <class T>
00055 bsta_kent<T>::bsta_kent(vcl_vector<vgl_plane_3d<T> > const& planes)
00056 {
00057   vnl_matrix<T> X(3,3,0);
00058   for (unsigned i=0; i<planes.size(); i++) {
00059     vgl_plane_3d<T> plane = planes[i];
00060     vgl_vector_3d<T> normal = plane.normal();
00061     vnl_matrix<T> n(1,3);
00062     n.put(0,0,normal.x());
00063     n.put(0,1,normal.y());
00064     n.put(0,2,normal.z());
00065     vnl_matrix<T> nt = n.transpose();
00066     X += nt*n;
00067   }
00068   X/=planes.size();
00069   vcl_cout << X << vcl_endl;
00070 
00071   vnl_matrix<T> X_inv = vnl_inverse(X);
00072   vnl_symmetric_eigensystem<T> E(X_inv);
00073   T t3 = E.get_eigenvalue(0); // smallest ??
00074   T t2 = E.get_eigenvalue(1);
00075   T t1 = E.get_eigenvalue(2); // largest??
00076 
00077   assert(t1 > t3);
00078 
00079   gamma3_ = E.get_eigenvector(0);  // check if this is the smallest values's vector
00080   gamma2_ = E.get_eigenvector(1);
00081   gamma1_ = E.get_eigenvector(2);
00082 
00083   vcl_cout << "gamma1->" << gamma1_ << vcl_endl
00084            << "gamma2->" << gamma2_ << vcl_endl
00085            << "gamma3->" << gamma3_ << vcl_endl;
00086 
00087   // compute the kent distr. parameters
00088   vnl_matrix<T> g3(3,1);
00089   g3.put(0,0,gamma3_.get(0));
00090   g3.put(1,0,gamma3_.get(1));
00091   g3.put(2,0,gamma3_.get(2));
00092   vnl_matrix<T> g3t = g3.transpose();
00093   vnl_matrix<T> res=(g3t*X_inv*g3);
00094   // make sure that res is 1x1
00095   T R = 1 - res.get(0,0);
00096   T Q = vcl_abs(t3-t2);
00097 
00098   kappa_= (1./(2.-2.*R-Q))+(1./(2.-2.*R+Q)); // always >= 0
00099   beta_= 0.5 * kappa_;
00100   vcl_cout << "kappa=" << kappa_ << "beta=" << beta_ << vcl_endl;
00101 }
00102 #endif // 0
00103 
00104 template <class T>
00105 T bsta_kent<T>::prob_density(vnl_vector_fixed<T,3> const& x)
00106 {
00107   T a=dot_product(x,gamma3_);
00108   T b=dot_product(x,gamma2_);
00109   T c=dot_product(x,gamma1_);
00110   T e=vcl_exp((kappa_*a)+(beta_*(b*b - c*c)));
00111   return e * normalizing_const();
00112 }
00113 
00114 template <class T>
00115 T bsta_kent<T>::normalizing_const(T kappa, T beta)
00116 {
00117   if (kappa<=0) kappa=kappa_; // the default
00118   if (beta <=0) beta= beta_;  // the default
00119   T denom = vcl_pow(2*vnl_math::pi, 1.5);
00120   denom*=vcl_pow(kappa, T(-0.5)); // so kappa should not be zero!
00121   T sum=0;
00122   for (int r=0; r<20; r++) {
00123     T f = vnl_gamma(r+1);
00124     T two_f = vnl_gamma(2*r+1);
00125     T x = vcl_pow(beta/kappa,2*r)*vnl_bessel(2*r/*+T(0.5)*/,kappa);
00126     sum += static_cast<T>(T(two_f)/T(f*f))* x;
00127   }
00128   denom*=sum; // which is 0 when beta==0, so also beta should not be zero!
00129   return T(1.0)/denom;
00130 }
00131 
00132 template <class T>
00133 void vsl_b_write(vsl_b_ostream & os, bsta_kent<T> const& sample)
00134 {
00135   vsl_b_write(os, sample.version());
00136   vsl_b_write(os, sample.kappa());
00137   vsl_b_write(os, sample.beta());
00138   vsl_b_write<T,3>(os, sample.minor_axis());
00139   vsl_b_write<T,3>(os, sample.major_axis());
00140   vsl_b_write<T,3>(os, sample.mean_direction());
00141 }
00142 
00143 template <class T>
00144 void vsl_b_write(vsl_b_ostream & os, bsta_kent<T> const* &sample)
00145 {
00146   if (sample) {
00147     vsl_b_write(os, *sample);
00148   }
00149 }
00150 
00151 template <class T>
00152 void vsl_b_read(vsl_b_istream & is, bsta_kent<T> &sample)
00153 {
00154   if (!is) return;
00155 
00156   short version;
00157   vsl_b_read(is,version);
00158   switch (version)
00159   {
00160     case 1:
00161       {T kappa, beta;
00162       vnl_vector_fixed<T,3> v1, v2, v3;
00163       vsl_b_read(is, kappa);
00164       vsl_b_read(is, beta);
00165       vsl_b_read<T,3>(is, v1);
00166       vsl_b_read<T,3>(is, v2);
00167       vsl_b_read<T,3>(is, v3);
00168       sample=bsta_kent<T>(kappa,beta,v1,v2,v3);
00169       break;}
00170     default:
00171       vcl_cerr << "I/O ERROR: vsl_b_read(vsl_b_istream&, bsta_kent<T>&)\n"
00172                << "           Unknown version number "<< version << '\n';
00173       is.is().clear(vcl_ios::badbit); // Set an unrecoverable IO error on stream
00174       break;
00175   }
00176 }
00177 
00178 template <class T>
00179 void vsl_b_read(vsl_b_istream & is, bsta_kent<T> *&sample)
00180 {
00181   vsl_b_read(is, *sample);
00182 }
00183 
00184 template <class T>
00185 vcl_ostream& operator<< (vcl_ostream& os, bsta_kent<T>& b)
00186 {
00187   return os << "kent: (kappa,beta) = (" << b.kappa() << "  " << b.beta() << ")\n";
00188 }
00189 
00190 #undef BSTA_KENT_INSTANTIATE
00191 #define BSTA_KENT_INSTANTIATE(T) \
00192 template class bsta_kent<T >; \
00193 template void vsl_b_write(vsl_b_ostream &, bsta_kent<T > const&); \
00194 template void vsl_b_write(vsl_b_ostream &, bsta_kent<T > const*&); \
00195 template void vsl_b_read(vsl_b_istream &, bsta_kent<T > &); \
00196 template void vsl_b_read(vsl_b_istream &, bsta_kent<T > *&); \
00197 template vcl_ostream& operator << (vcl_ostream &, bsta_kent<T > &)
00198 
00199 #endif