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);
00024 T t2 = E.get_eigenvalue(1);
00025 T t1 = E.get_eigenvalue(2);
00026
00027 assert(t1 > t3);
00028
00029 gamma3_ = E.get_eigenvector(0);
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
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
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));
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);
00074 T t2 = E.get_eigenvalue(1);
00075 T t1 = E.get_eigenvalue(2);
00076
00077 assert(t1 > t3);
00078
00079 gamma3_ = E.get_eigenvector(0);
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
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
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));
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_;
00118 if (beta <=0) beta= beta_;
00119 T denom = vcl_pow(2*vnl_math::pi, 1.5);
00120 denom*=vcl_pow(kappa, T(-0.5));
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,kappa);
00126 sum += static_cast<T>(T(two_f)/T(f*f))* x;
00127 }
00128 denom*=sum;
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);
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