contrib/gel/mrc/vpgl/vpgl_poly_radial_distortion.txx
Go to the documentation of this file.
00001 // This is gel/mrc/vpgl/vpgl_poly_radial_distortion.txx
00002 #ifndef vpgl_poly_radial_distortion_txx_
00003 #define vpgl_poly_radial_distortion_txx_
00004 //:
00005 // \file
00006 
00007 #include "vpgl_poly_radial_distortion.h"
00008 
00009 #if VCL_CAN_DO_PARTIAL_SPECIALIZATION
00010 
00011 // The templated helper functions are a metaprogram which allows the
00012 // compiler to create a closed form (no loops) expression for polynomial
00013 // evaluation of any order.  For very large n loops may be more efficient
00014 // but for lens distortion the order is usually small.
00015 
00016 template <class T, int n>
00017 struct vpgl_poly_helper{
00018   static inline T val(const T& radius, const T* k)
00019   {
00020     return ((*k)+vpgl_poly_helper<T,n-1>::val(radius, k+1))*radius;
00021   }
00022 };
00023 
00024 template <class T>
00025 struct vpgl_poly_helper<T,1>{
00026   static inline T val(const T& radius, const T* k)
00027   {
00028     return (*k)*radius;
00029   }
00030 };
00031 
00032 
00033 //: Distort a radial length
00034 template <class T, int n>
00035 T
00036 vpgl_poly_radial_distortion<T,n>::distort_radius( T radius ) const
00037 {
00038   return 1 + vpgl_poly_helper<T,n>::val(radius, coefficients_);
00039 }
00040 
00041 
00042 //====================================================================
00043 
00044 
00045 template <class T, int n>
00046 struct vpgl_poly_deriv_helper{
00047   static inline T val(const T& radius, const T* k, unsigned int p)
00048   {
00049     return p*(*k) + vpgl_poly_deriv_helper<T,n-1>::val(radius, k+1, p+1)*radius;
00050   }
00051 };
00052 
00053 
00054 template <class T>
00055 struct vpgl_poly_deriv_helper<T,1>{
00056   static inline T val(const T& /*radius*/, const T* k, unsigned int p)
00057   {
00058     return p*(*k);
00059   }
00060 };
00061 
00062 //: Compute the derivative of the distort_radius function
00063 template <class T, int n>
00064 T
00065 vpgl_poly_radial_distortion<T,n>::distort_radius_deriv( T radius ) const
00066 {
00067   return vpgl_poly_deriv_helper<T,n>::val(radius, coefficients_, 1);
00068 }
00069 
00070 
00071 #else // VCL_CAN_DO_PARTIAL_SPECIALIZATION
00072 
00073 // If we can not use partial template instantiation we loop instead.
00074 
00075 //: Distort a radial length
00076 template <class T, int n>
00077 T
00078 vpgl_poly_radial_distortion<T,n>::distort_radius( T radius ) const
00079 {
00080   T value = T(0);
00081   for (int i=n-1; i>=0; --i){
00082     value = (coefficients_[i]+value)*radius;
00083   }
00084   return 1 + value;
00085 }
00086 
00087 //: Compute the derivative of the distort_radius function
00088 template <class T, int n>
00089 T
00090 vpgl_poly_radial_distortion<T,n>::distort_radius_deriv( T radius ) const
00091 {
00092   T value = T(0);
00093   for (int i=n-1; i>=0; --i){
00094     value = (i+1)*coefficients_[i] + value*radius;
00095   }
00096   return value;
00097 }
00098 
00099 #endif // VCL_CAN_DO_PARTIAL_SPECIALIZATION
00100 
00101 // Code for easy instantiation.
00102 #undef vpgl_POLY_RADIAL_DISTORTION_INSTANTIATE
00103 #define vpgl_POLY_RADIAL_DISTORTION_INSTANTIATE(T,n) \
00104 template class vpgl_poly_radial_distortion<T,n>
00105 
00106 #endif // vpgl_poly_radial_distortion_txx_