contrib/rpl/rgrl/rgrl_feature_trace_pt.cxx
Go to the documentation of this file.
00001 #include "rgrl_feature_trace_pt.h"
00002 //:
00003 // \file
00004 // \author Amitha Perera
00005 // \date   Feb 2003
00006 
00007 #include "rgrl_transformation.h"
00008 #include "rgrl_util.h"
00009 #include <vnl/algo/vnl_svd.h>
00010 
00011 #include <vcl_cassert.h>
00012 
00013 #include <rgrl/rgrl_cast.h>
00014 
00015 rgrl_feature_trace_pt ::
00016 rgrl_feature_trace_pt()
00017   : rgrl_feature(),
00018     subspace_cached_( false ),
00019     length_( 0 ), radius_( 0 )
00020 {
00021   
00022 }
00023 
00024 rgrl_feature_trace_pt::
00025 rgrl_feature_trace_pt( vnl_vector<double> const& loc,
00026                        vnl_vector<double> const& tangent )
00027   : rgrl_feature( loc ),
00028     tangent_( tangent ),
00029     error_proj_( loc.size(), loc.size(), vnl_matrix_identity ),
00030     subspace_cached_(false),
00031     length_( 0 ), radius_( 0 )
00032 {
00033   tangent_.normalize();
00034   error_proj_ -= outer_product( tangent_, tangent_ );
00035 }
00036 
00037 rgrl_feature_trace_pt::
00038 rgrl_feature_trace_pt( vnl_vector<double> const& loc,
00039                        vnl_vector<double> const& tangent,
00040                        double                    length,
00041                        double                    radius )
00042   : rgrl_feature( loc ),
00043     tangent_( tangent ),
00044     error_proj_( loc.size(), loc.size(), vnl_matrix_identity ),
00045     subspace_cached_(false),
00046     length_( length ), radius_( radius )
00047 {
00048   tangent_.normalize();
00049   error_proj_ -= outer_product( tangent_, tangent_ );
00050 }
00051 
00052 
00053 
00054 unsigned int
00055 rgrl_feature_trace_pt::
00056 num_constraints() const
00057 {
00058   return location_.size()-1;
00059 }
00060 
00061 vnl_vector<double> const&
00062 rgrl_feature_trace_pt::
00063 tangent() const
00064 {
00065   return tangent_;
00066 }
00067 
00068 
00069 vnl_matrix<double> const&
00070 rgrl_feature_trace_pt::
00071 error_projector() const
00072 {
00073   return error_proj_;
00074 }
00075 
00076 rgrl_feature_sptr
00077 rgrl_feature_trace_pt::
00078 transform( rgrl_transformation const& xform ) const
00079 {
00080   rgrl_feature_trace_pt* result = new rgrl_feature_trace_pt( );
00081 
00082   // capture the allocation into a smart pointer for exception safety.
00083   rgrl_feature_sptr result_sptr = result;
00084 
00085   // Transform the location and tangent
00086   //
00087   xform.map_location( this->location_, result->location_ );
00088   xform.map_tangent( this->location_, this->tangent_, result->tangent_ );
00089 
00090   // The constructor above created an identity projection matrix
00091   //
00092   result->error_proj_.set_size( this->location_.size(), this->location_.size() );
00093   result->error_proj_.set_identity();
00094   result->error_proj_ -= outer_product( result->tangent_, result->tangent_ );
00095 
00096   //  Set the radius and length.  If these values truly must be
00097   //  transformed, then the function transform_region should used.
00098 
00099   result -> radius_ = this -> radius_;
00100   result -> length_ = this -> length_;
00101 
00102   return result_sptr;
00103 }
00104 
00105 vnl_matrix<double> const&
00106 rgrl_feature_trace_pt ::
00107 normal_subspace()
00108 {
00109   if ( subspace_cached_ )
00110     return normal_subspace_;
00111 
00112   //  Find the basis of the normal subspace from the null space of the
00113   //  single row matrix containing just the tangent direction.
00114 
00115   vnl_matrix<double> one_row( 1, this -> tangent_.size() );
00116   one_row.set_row( 0, this -> tangent_ );
00117   vnl_svd<double> tangent_svd( one_row );
00118   normal_subspace_ = tangent_svd.nullspace();
00119   assert( normal_subspace_ . columns() == this -> tangent_ . size() - 1 );
00120   subspace_cached_ = true;
00121   return normal_subspace_;
00122 }
00123 
00124 rgrl_feature_trace_pt::feature_vector
00125 rgrl_feature_trace_pt::
00126 boundary_points(vnl_vector<double> const& in_direction) const
00127 {
00128   //1. Compute the vector normal to the tangent lying in the same plane as the tangent
00129   //   and in_direction.
00130   //
00131   vnl_vector<double> normal(location_.size());
00132   if (location_.size() == 2) { //for 2D, just rotate the tangent_ by pi/2
00133     normal[0] = -tangent_[1];
00134     normal[1] =  tangent_[0];
00135   }
00136   else { // Gram-Schmidt Orthogonalization
00137     normal = in_direction -
00138       dot_product(tangent_, in_direction)*tangent_;
00139     normal.normalize();
00140   }
00141 
00142   //2. find the 2 boundary points in the direction of the normal,
00143   //   and create 2 rgrl_feature_trace_pt, with the centers shifted to the boundaries,
00144   //   tangent_ the same and no radius and length.
00145   //
00146   feature_vector bdy_feature_points;
00147   rgrl_feature_sptr bd_pt = new rgrl_feature_trace_pt( location_+(normal*radius_), tangent_ );
00148   bdy_feature_points.push_back(bd_pt);
00149   bd_pt = new rgrl_feature_trace_pt( location_-(normal*radius_), tangent_ );
00150   bdy_feature_points.push_back(bd_pt);
00151 
00152   return bdy_feature_points;
00153 }
00154 
00155 //:  Compute the signature weight between two features.
00156 double
00157 rgrl_feature_trace_pt ::
00158 absolute_signature_weight( rgrl_feature_sptr other ) const
00159 {
00160   //if other is invalid
00161   if ( !other )  return 0.0;
00162 
00163   rgrl_feature_trace_pt* trace_ptr = rgrl_cast<rgrl_feature_trace_pt*>(other);
00164   assert( trace_ptr );
00165   double dir_wgt = vcl_abs( dot_product( this->tangent_, trace_ptr->tangent_ ) );
00166 
00167   double scale_wgt = 1;
00168   if ( this->scale_ && trace_ptr->scale_ ) {
00169     if ( this->scale_ >= trace_ptr->scale_ )
00170       scale_wgt = trace_ptr->scale_ / this->scale_;
00171     else
00172       scale_wgt = this->scale_ / trace_ptr->scale_;
00173     // the weight change is too gradual, make it more steep
00174     // scale_wgt = scale_wgt * scale_wgt;
00175   }
00176 
00177   return  dir_wgt* vcl_sqrt(scale_wgt);
00178 }
00179 
00180 //: write out feature
00181 void
00182 rgrl_feature_trace_pt::
00183 write( vcl_ostream& os ) const
00184 {
00185   // tag
00186   os << "TRACE" << vcl_endl;
00187   
00188   // dim
00189   os << location_.size() << vcl_endl;
00190   
00191   // atributes
00192   os << location_ << "    " << scale_ << "\n"
00193      << tangent_ << "\n" 
00194      << error_proj_ << vcl_endl;
00195 }
00196 
00197 //: read in feature
00198 bool 
00199 rgrl_feature_trace_pt::
00200 read( vcl_istream& is, bool skip_tag )
00201 {
00202   if( !skip_tag ) {
00203 
00204     // skip empty lines
00205     rgrl_util_skip_empty_lines( is );
00206     
00207     vcl_string str;
00208     vcl_getline( is, str );
00209     
00210     // The token should appear at the beginning of line
00211     if ( str.find( "TRACE" ) != 0 ) {
00212       WarningMacro( "The tag is not TRACE. reading is aborted.\n" );
00213       return false;
00214     }
00215   }
00216 
00217   // get dim
00218   int dim=-1;
00219   is >> dim;
00220   
00221   if( !is || dim<=0 ) 
00222     return false;    // cannot get dimension
00223     
00224   // get location
00225   location_.set_size( dim );
00226   is >> location_;
00227   if( !is )
00228     return false;   // cannot read location
00229     
00230   // get scale
00231   is >> scale_; 
00232   if( !is )
00233     return false;   // cannot read scale
00234 
00235   // get tangent
00236   tangent_.set_size( dim );
00237   is >> tangent_;
00238   if( !is ) 
00239     return false; 
00240     
00241   // get error projector
00242   error_proj_.set_size( dim, dim );
00243   is >> error_proj_;
00244   if( !is ) 
00245     return false; 
00246   
00247   //reset flag
00248   subspace_cached_ = false;
00249   
00250   return true;
00251 }
00252 
00253 rgrl_feature_sptr
00254 rgrl_feature_trace_pt::
00255 clone() const
00256 {
00257   return new rgrl_feature_trace_pt(*this);
00258 }