contrib/rpl/rgrl/rgrl_feature_trace_region.cxx
Go to the documentation of this file.
00001 // \file
00002 // \author Amitha Perera
00003 // \date   Feb 2003
00004 
00005 #include "rgrl_feature_trace_region.h"
00006 #include <rgrl/rgrl_transformation.h>
00007 #include <rgrl/rgrl_util.h>
00008 #include <rgrl/rgrl_cast.h>
00009 #include <vnl/algo/vnl_svd.h>
00010 
00011 #include <vcl_cassert.h>
00012 // not used? #include <vcl_iostream.h>
00013 
00014 rgrl_feature_trace_region::
00015 rgrl_feature_trace_region( vnl_vector<double> const& loc,
00016                        vnl_vector<double> const& tangent )
00017   : rgrl_feature_trace_pt( loc, tangent ),
00018     region_length_( 0 ), region_radius_( 0 )
00019 {
00020 }
00021 
00022 rgrl_feature_trace_region::
00023 rgrl_feature_trace_region( vnl_vector<double> const& loc,
00024                            vnl_vector<double> const& tangent,
00025                            double                    region_length,
00026                            double                    region_radius )
00027   : rgrl_feature_trace_pt( loc, tangent ),
00028     region_length_( region_length ), region_radius_( region_radius )
00029 {
00030 }
00031 
00032 
00033 rgrl_feature_trace_region::
00034 rgrl_feature_trace_region( )
00035   : rgrl_feature_trace_pt(),
00036     region_length_( 0 ), region_radius_( 0 )
00037 {
00038 }
00039 
00040 
00041 unsigned int
00042 rgrl_feature_trace_region::
00043 num_constraints() const
00044 {
00045   return location_.size() - 1;
00046 }
00047 
00048 rgrl_feature_sptr
00049 rgrl_feature_trace_region::
00050 transform( rgrl_transformation const& xform ) const
00051 {
00052   rgrl_feature_trace_region* result = new rgrl_feature_trace_region();
00053 
00054   // capture the allocation into a smart pointer for exception safety.
00055   rgrl_feature_sptr result_sptr = result;
00056 
00057   // Transform the location and tangent
00058   //
00059   xform.map_location( this->location_, result->location_ );
00060   xform.map_tangent( this->location_, this->tangent_, result->tangent_ );
00061 
00062   // The constructor above created an identity projection matrix
00063   //
00064   result->error_proj_.set_size( this->location_.size(), this->location_.size() );
00065   result->error_proj_.set_identity();
00066   result->error_proj_ -= outer_product( result->tangent_, result->tangent_ );
00067 
00068   //  Set the radius and length.  If these values truly must be
00069   //  transformed, then the function transform_region should used.
00070 
00071   result -> region_radius_ = this -> region_radius_;
00072   result -> region_length_ = this -> region_length_;
00073 
00074   return result_sptr;
00075 }
00076 
00077 
00078 rgrl_feature_sptr
00079 rgrl_feature_trace_region::
00080 transform_region( rgrl_transformation const& xform ) const
00081 {
00082   //  Transform the location and direction
00083   rgrl_feature_sptr result_sptr = this -> transform( xform );
00084 
00085   //  Cast down the pointer so that we can set the specific variables.
00086   rgrl_feature_trace_region * trace_ptr
00087     = rgrl_cast<rgrl_feature_trace_region *> ( result_sptr );
00088 
00089   //  Determine the length along the tangent direction.  Map a point
00090   //  that is half length units from the mapped center location along
00091   //  tangent direction and compute the double distance between this
00092   //  point and the mapped location.
00093 
00094   vnl_vector< double > end_point( this -> location_ . size() );
00095   xform . map_location( this -> location_ + this -> region_length_ / 2.0
00096                         * this -> tangent_, end_point );
00097   trace_ptr -> region_length_ = ( end_point - trace_ptr -> location_ ) . magnitude() * 2.0;
00098 
00099   //  The radius is tougher.  First, find the basis of the tangent
00100   //  subspace from the null space of the single row matrix
00101   //  containing just the tangent direction.
00102 
00103   vnl_matrix<double> one_row( 1, this -> tangent_.size() );
00104   one_row.set_row( 0, this -> tangent_ );
00105   vnl_svd<double> tangent_svd( one_row );
00106   vnl_matrix<double> nullspace = tangent_svd.nullspace();
00107   assert( nullspace . columns() == this -> tangent_ . size() - 1 );
00108 
00109   //  Now, for each basis vector, map a point radius units away from
00110   //  the location along the vector.  Compute the distance of the
00111   //  resulting point from the mapped location.  Average these to
00112   //  come up with the radius.
00113 
00114   vnl_vector< double > point_along_dir( this -> location_ . size() );
00115   double sum_radii = 0;
00116 
00117   double this_region_radius = this->region_radius_; // Work-around for Borland C++ 5.
00118   for ( unsigned int i=0; i+1 < this -> location_ . size(); ++i )
00119   {
00120     point_along_dir = this -> location();
00121     point_along_dir += this_region_radius * nullspace . get_column( i );
00122     xform . map_location( point_along_dir, end_point );
00123     sum_radii += ( end_point - trace_ptr -> location_ ) . magnitude();
00124   }
00125 
00126   trace_ptr -> region_radius_ = sum_radii / ( this -> location_ . size() - 1 );
00127 
00128   return result_sptr;
00129 }
00130 
00131 // Return region(neighboring) pixels in "pixel" coordinates.
00132 void
00133 rgrl_feature_trace_region ::
00134 generate_pixel_coordinates( vnl_vector< double > const&  spacing_ratio )
00135 {
00136   //  Create the oriented rectangular solid.  Form the set of
00137   //  orthogonal directions and radii.  The directions are combined
00138   //  from the tangent direction and the basis for the normal
00139   //  subspace.  The first radius is half the length of the region.
00140   //  The others are all equal to the radius of the trace region.
00141 
00142   unsigned dim = this -> location_ . size();
00143   vnl_matrix< double > normals = this -> normal_subspace();
00144   vcl_vector< vnl_vector<double> > directions;
00145   directions . reserve( dim );
00146 
00147   vnl_vector< double > radii_in_pixel( dim );
00148   vnl_vector< double > location_in_pixel( dim );
00149   vnl_vector< double > direction_in_pixel( dim );
00150 
00151   // convert directions and location to the pixel coordinates
00152   for ( unsigned i = 0; i < dim; ++i )
00153   {
00154     direction_in_pixel[ i ] = this->tangent_[ i ] / spacing_ratio[ i ];
00155     location_in_pixel[ i ] = this->location_[ i ] / spacing_ratio[ i ];
00156   }
00157   directions . push_back( direction_in_pixel );
00158 
00159   radii_in_pixel[ 0 ] = this -> region_length_ / spacing_ratio[ 0 ] / 2.0 ;
00160   for ( unsigned i = 0; i < dim-1; ++i )
00161   {
00162     direction_in_pixel = normals.get_column( i );
00163     for ( unsigned j = 0; j < dim; ++j )
00164       direction_in_pixel[ j ] /= spacing_ratio[ j ];
00165 
00166     directions.push_back( direction_in_pixel );
00167     radii_in_pixel[ i+1 ] = this -> region_radius_ / spacing_ratio[ i+1 ];
00168   }
00169 
00170   //  Call the utility function to extract the pixel locations,
00171   //  record the caching and return the vector.
00172 
00173   rgrl_util_extract_region_locations( location_in_pixel, directions,
00174                                       radii_in_pixel, pixel_coordinates_ );
00175   pixel_coordinates_cached_ = true;
00176 }