contrib/rpl/rrel/rrel_lts_obj.cxx
Go to the documentation of this file.
00001 // This is rpl/rrel/rrel_lts_obj.cxx
00002 #include "rrel_lts_obj.h"
00003 
00004 #include <vnl/vnl_math.h>
00005 
00006 #include <vcl_algorithm.h>
00007 #include <vcl_vector.h>
00008 
00009 #include <vcl_cassert.h>
00010 
00011 rrel_lts_obj::rrel_lts_obj( unsigned int num_sam_inst, double inlier_frac )
00012   : num_sam_inst_( num_sam_inst ),
00013     inlier_frac_( inlier_frac )
00014 {
00015 }
00016 
00017 rrel_lts_obj::~rrel_lts_obj()
00018 {
00019 }
00020 
00021 
00022 double
00023 rrel_lts_obj::fcn( vect_const_iter begin, vect_const_iter end,
00024                    vect_const_iter /*scale begin*/,
00025                    vnl_vector<double>* /*param_vector*/ ) const
00026 {
00027   return fcn( begin, end, 0.0, (vnl_vector<double>*)0 );
00028 }
00029 
00030 
00031 double
00032 rrel_lts_obj::fcn( vect_const_iter begin, vect_const_iter end,
00033                    double /*scale*/,
00034                    vnl_vector<double>* /*param_vector*/ ) const
00035 {
00036   // 1. We need to sort the squared residuals.
00037 
00038   // Since we know that vect_const_iter is vector::iterator, we can
00039   // use the size of the incoming vector to preallocate the sq_res
00040   // vector. If/when this becomes more general, the we can remove the
00041   // preallocation if necessary. The cost of a few reallocs as we
00042   // compute the squared residuals are unlikely to seriously affect
00043   // anything.
00044 
00045   vcl_vector<double> sq_res;
00046   sq_res.reserve( end - begin );
00047   for ( ; begin != end; ++begin ) {
00048     sq_res.push_back( (*begin) * (*begin) );
00049   }
00050 
00051   unsigned int num_residuals = sq_res.size();
00052   assert( num_residuals >= num_sam_inst_ );
00053 
00054   // 2. Find the index of the "median value" if the residuals are sorted.
00055 
00056   unsigned int index;
00057   if ( inlier_frac_ == 0.5 ) 
00058     index = (num_residuals-num_sam_inst_)/2 + num_sam_inst_;
00059   else
00060     index = vnl_math_rnd( (num_residuals-num_sam_inst_)*inlier_frac_ ) + num_sam_inst_;
00061   if ( index >= num_residuals ) index = num_residuals-1;
00062 
00063   // 3. Sort the squared residuals so that all the smallest residuals
00064   // are in positions less than index.
00065   vcl_vector<double>::iterator loc = sq_res.begin() + index;
00066   vcl_nth_element( sq_res.begin(), loc, sq_res.end() );
00067 
00068   // 4. Sum them up.
00069   double sum=0;
00070   for ( unsigned int i=0; i<=index; ++i )
00071     sum += sq_res[i];
00072 
00073   return sum;
00074 }
00075