contrib/rpl/rgrl/rgrl_mask_oriented_box.cxx
Go to the documentation of this file.
00001 #include "rgrl_mask_oriented_box.h"
00002 //:
00003 // \file
00004 
00005 #include <vcl_cassert.h>
00006 #include <vcl_limits.h>
00007 #include <vnl/vnl_transpose.h>
00008 
00009 //******************** mask using an oriented box ***********************
00010 
00011 rgrl_mask_oriented_box::
00012 rgrl_mask_oriented_box( unsigned dim )
00013   : rgrl_mask( dim ),
00014     omin_(dim),
00015     omax_(dim),
00016     axes_(dim, dim)
00017 {
00018 }
00019 
00020 rgrl_mask_oriented_box::
00021 rgrl_mask_oriented_box( vnl_vector<double> const& x0,
00022                         vnl_matrix<double> const& axes,
00023                         vnl_vector<double> const& len )
00024   : rgrl_mask( x0.size() ),
00025     axes_( axes )
00026 {
00027   assert( x0.size() == len.size() );
00028   assert( x0.size() == axes.rows());
00029   assert( x0.size() == axes.cols());
00030 
00031   omin_ = vnl_transpose( axes ) * x0;
00032   omax_ = omin_;
00033   omax_ += len;
00034 
00035   update_bounding_box();
00036 }
00037 
00038 rgrl_mask_oriented_box::
00039 rgrl_mask_oriented_box( vnl_vector<double> const& oriented_xmin,
00040                         vnl_vector<double> const& oriented_xmax,
00041                         vnl_matrix<double> const& axes )
00042   : rgrl_mask( oriented_xmin.size() ),
00043     omin_( oriented_xmin ),
00044     omax_( oriented_xmax ),
00045     axes_( axes )
00046 {
00047   assert( oriented_xmin.size() == oriented_xmax.size() );
00048   assert( oriented_xmin.size() == axes.rows() );
00049   assert( oriented_xmin.size() == axes.cols() );
00050 
00051   update_bounding_box();
00052 }
00053 
00054 bool
00055 rgrl_mask_oriented_box::
00056 inside( vnl_vector<double> const& pt ) const
00057 {
00058   assert( pt.size() == omin_.size() );
00059 
00060   vnl_vector<double> mapped = vnl_transpose( axes_ ) * pt;
00061 
00062   // len_[i] >=0 is guaranteed in update_bounding_box function
00063   //
00064   bool inside = true;
00065   for ( unsigned i=0; i<omin_.size()&&inside; ++i )
00066     inside = mapped[i] >= omin_[i] && mapped[i] <= omax_[i];
00067 
00068   return inside;
00069 }
00070 
00071 void
00072 rgrl_mask_oriented_box::
00073 set_len( vnl_vector<double> const& len )
00074 {
00075   assert( len.size() == omin_.size() );
00076   omax_ = omin_ + len;
00077 
00078   update_bounding_box();
00079 }
00080 
00081 void
00082 rgrl_mask_oriented_box::
00083 set_axes( vnl_matrix<double> const& axes )
00084 {
00085   // square matrix
00086   assert( axes.rows() == axes.cols() );
00087 
00088   axes_ = axes;
00089 
00090   update_bounding_box();
00091 }
00092 
00093 //: the lower coordinate of the box.
00094 vnl_vector<double>
00095 rgrl_mask_oriented_box::
00096 origin() const
00097 {
00098   return axes_*omin_;
00099 }
00100 
00101 void
00102 rgrl_mask_oriented_box::
00103 update_bounding_box()
00104 {
00105   assert( omin_.size() == omax_.size() );
00106   assert( omin_.size() == axes_.rows());
00107   assert( omin_.size() == axes_.cols());
00108 
00109   const unsigned int dim = omin_.size();
00110 
00111   // Extra step:
00112   // make sure len_[i] >=0
00113   //
00114   for ( unsigned i=0; i<dim; ++i )
00115     if ( omin_[i] > omax_[i] ) {
00116 
00117       // swap omin_[i] and omax_[i]
00118       double d = omax_[i];
00119       omax_[i] = omin_[i];
00120       omin_[i] = d;
00121       // invert the column vector
00122       for ( unsigned j=0; j<dim; ++j )
00123         axes_(j, i) = -axes_(j,i);
00124     }
00125 
00126   // use bit pattern to generate all corners
00127   const unsigned num_corners = 2<<dim;
00128 
00129   vnl_vector<double> xmin ( axes_*omin_ );
00130   vnl_vector<double> xmax ( xmin );
00131   vnl_vector<double> oriented_pt, pt;
00132   for ( unsigned i=1; i<num_corners; ++i ) {
00133 
00134     oriented_pt = omin_;
00135     // going through exes
00136     for ( unsigned j=0; j<dim; ++j ) {
00137 
00138       // selection using each bit 0/1
00139       if ( (i>>j)&0x1 )
00140         oriented_pt[j] = omax_[j];
00141     }
00142 
00143     pt = axes_ * oriented_pt;
00144     for ( unsigned j=0; j<dim; ++j ) {
00145       if ( pt[j] < xmin[j] )   xmin[j] = pt[j];
00146       if ( pt[j] > xmax[j] )   xmax[j] = pt[j];
00147     }
00148   }
00149 
00150   x0_ = xmin;
00151   x1_ = xmax;
00152 }
00153 
00154 //: get average distance of corresponding vertices between two oriented box
00155 double
00156 rgrl_mask_oriented_box::
00157 average_vertices_dist( const rgrl_mask_oriented_box& other ) const
00158 {
00159   if ( omin_.size() != other.omin_.size() )
00160     return vcl_numeric_limits<double>::infinity();
00161 
00162   const unsigned int dim = omin_.size();
00163   double cum_dist = 0.0;
00164 
00165   // use bit pattern to generate all corners
00166   const unsigned num_pts = 2<<dim;
00167   vnl_vector<double> pt, other_pt;
00168   for ( unsigned i=0; i<num_pts; ++i ) {
00169 
00170     pt = omin_;
00171     other_pt = other.omin_;
00172 
00173     // going through exes
00174     for ( unsigned j=0; j<dim; ++j ) {
00175 
00176       // multiplication using each bit 0/1
00177       const bool use_max = ((i>>j)&0x1);
00178       if ( use_max ) {
00179         pt[j] = omax_[j];
00180         other_pt[j] = other.omax_[j];
00181       }
00182     }
00183 
00184     cum_dist += (axes_*pt - other.axes()*other_pt).two_norm();
00185   }
00186   return cum_dist/num_pts;
00187 }
00188 
00189 bool
00190 rgrl_mask_oriented_box::
00191 operator==( const rgrl_mask_oriented_box& other ) const
00192 {
00193   // check the axes first
00194   // axes are othogonal matrix
00195   // therefore the product should be identity matrix
00196   vnl_matrix<double> prod = vnl_transpose( this->axes_ ) * other.axes_;
00197   vnl_matrix<double> eye( omin_.size(), omin_.size() );
00198   eye.set_identity();
00199   if ( (prod - eye).fro_norm() > 1e-4 ) {
00200     WarningMacro( "Incompatible axes. oriented boxes cannot be compared. " << vcl_endl );
00201     return false;
00202   }
00203 
00204   // now check omin_ and len_
00205   //
00206   return omin_ == other.omin_  &&
00207          omax_ == other.omax_;
00208 }
00209 
00210 bool
00211 rgrl_mask_oriented_box::
00212 operator!=( const rgrl_mask_oriented_box& other ) const
00213 {
00214   return !( *this == other );
00215 }
00216 
00217 vcl_ostream& operator<<(vcl_ostream& os, const rgrl_mask_oriented_box& box)
00218 {
00219   os<< box.oriented_x0().size() << "  ";
00220   if ( box.oriented_x0().size() ) {
00221     os << box.oriented_x0()<<"  "<<box.oriented_x1() << '\n'
00222        << box.axes() << vcl_endl;
00223   }
00224   return os;
00225 }
00226 
00227 vcl_istream& operator>>(vcl_istream& is, rgrl_mask_oriented_box& box)
00228 {
00229   int m = -1;
00230   is >> m;
00231 
00232   if ( m <= 0 ) return is;
00233 
00234   vnl_vector<double> x0(m), x1(m);
00235   is >> x0 >> x1;
00236 
00237   vnl_matrix<double> axes(m, m);
00238   is >> axes;
00239 
00240   rgrl_mask_oriented_box temp_box( x0, x1, axes );
00241   box = temp_box;
00242   return is;
00243 }
00244